H@H + nginx 4层代理设置教程

前言

最近购入了一个大盘鸡,除了作为离线下载工具外,还想挂着H@H赚点hath花花,遂有以下类似备忘录的教程。

由于本人对nginx最为熟悉,虽然也有haproxy等代理软件,但是同一台服务器上只要有nginx就足够了,布局简单也最好用;个人想法是不要重复搬轮子,这对自己身体并不是很好。

本文也是建立在前人的肩膀上罢了,提前谢谢观赏。

本人的账户情况

安装过程

nginx的4层(TCP)代理需要使用stream模块,需要注意。

本人使用debian 13系统,默认存储库即可用,若是其他系统需要注意默认模块是否包含以上提到的stream模块。

nginx -V

查看是否有 --with-stream即可。

本次教程用的是docker容器的hath-rust,也可以直接使用二进制文件,反正软件的参数都一样。

1. 安装nginx以及stream模块

sudo apt install nginx libnginx-mod-stream

碎碎念:国内好多教程只教如何编译nginx模块,明明存储库里有(apt search libnginx),根本不需要多此一举;而且目录规范,不需要额外配置。

即可。

2. nginx配置

打开 nginx.conf配置文件编辑。

vim /etc/nginx/nginx.conf

以下为配置文件示例:

user www-data;
worker_processes auto;
worker_cpu_affinity auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

# 以上的不用修改

# 4层(tcp)代理
stream {

    # SNI 识别,将域名映射成一个配置名
    map $ssl_preread_server_name $backend_name {
        hostnames; #加上这个能加快map识别分流速度

        www.b2og.com www;
        # ......
        *.hath.network hath_proxy;
        default default;
    }

    upstream www {

        server 127.0.0.1:10101;
    }

    # ......

    upstream hath_proxy {

        server 127.0.0.1:10103;
    }

    upstream hath {

        server 127.0.0.1:8585;
    }

    upstream default {

        server 127.0.0.1:80; #默认请求
    }

    log_format basic '$proxy_protocol_addr '
    '$protocol $status $bytes_sent $bytes_received '
    '$session_time ';

    # 监听 443 并开启 ssl_preread 用于识别sni
    server {

        listen 443 reuseport;
        listen [::]:443 reuseport;
        proxy_pass $backend_name;
        proxy_protocol on; #使用proxy_protocol用于其他4层以及7层的真实ip识别
        ssl_preread on;
    }

    # 由于h@h客户端不支持proxy_protocol,因此再转发一遍卸载掉proxy_protocol
    server {
        listen 10103 proxy_protocol;
        proxy_pass  hath;
    }

}

# 7层(http)代理
http {
        # ......
        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
        
        # 以上的无需修改,下面的server配置自行按需添加。
        # 当然最好还是将server配置放在sites-available目录中,并软连接到sites-enabled目录中,这样看着不乱

        # 用于切换ws连接
        map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
        }


        #www配置
        server {
            listen 10101 ssl reuseport proxy_protocol; # 这就是监听上面配置给4层(示例的www配置的10101端口);而且由于开启了proxy_protocol,这里也需要加上
            listen [::]:10101 ssl reuseport proxy_protocol;
            server_name www.b2og.com;
            
            http2 on;
          
            gzip_http_version 1.1;
            gzip_vary on;
            gzip_comp_level 6;
            gzip_proxied any;
            gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript;

            ssl_protocols TLSv1.2 TLSv1.3;
            ssl_certificate /path/to/cert.pem;
            ssl_certificate_key /path/to/key.pem;

            location / {

                proxy_pass http://localhost:8080/;
                proxy_set_header HOST $http_host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $proxy_protocol_addr; #通过proxy_protocol获取的ip
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
               }

            # ws连接
            location /ws {

                proxy_pass http://localhost:8081/;
                proxy_set_header HOST $http_host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $proxy_protocol_addr; #通过proxy_protocol获取的ip
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
                # 以下两个header用于切换ws
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
               }
                
         }

         # ......其他server配置
}

这样的4层加7层代理转发就配置好了。4层代理由于是更底层的tcp/udp代理,因此不只是这个H@H,其他的例如mariadb,ftp,dns(udp)都可以通过4层转发,H@H只是例子。

而且这种先识别sni再转发流量的方式好处很多,不但可以全服务器端口包括ssh都可以通过一个端口转发;并且可以做到证书不泄露,也就是只输入ip是不可能通过不匹配的证书知道域名的,再配合使用cdn即可做到源站ip不泄露;这样共用一个端口也可以做到流量伪装,别人无法知道你后端究竟在运行什么服务...等等。

(可选)docker版hath-rust设置

由于我需要对hath限一下速,用docker容器是比较方便的,以下介绍一下方法。

这次使用的不是官方作者打包的hath-rust镜像,是我自己打包的镜像,这个镜像基本只包含hath-rust这个可执行文件,小于5MB。占用空间极小,欢迎使用,查看Dokcer镜像以及Dockerfile仓库

最好是使用一个专用的用户来运行这个服务,防止你的服务器因为漏洞出现问题。

sudo useradd -m -d /home/hath -s /bin/bash hath
su - hath

其中: -m:创建用户的主目录。 -d:指定用户的主目录路径。 -s:指定用户的 shell;并且使用su命令切换用户。

使用以下命令开启容器即可启动hath-rust。

docker run  -it  \
  --name hath \
  -p 8585:8585  \
  -v ./hath:/hath  \
  --user "$(id -u):$(id -g)"  \
  grandduke1106/hath-rust-docker  \
  --port 8585 --disable-ip-origin-check

其中:

  • -it: 开启交互模式并分配一个终端,在输入id和密码成功运行后即可去除这个参数改为-d用于后台运行。
  • --name hath: 定义容器名字为hath
  • -p 8585:8585: 用于指定端口映射,刚刚的nginx示例使用8585端口,因此这里也是。
  • -v ./hath:/hath: 将当前路径下的 hath 目录挂载到容器内的 /hath 工作目录,用于持久化存储数据。
  • --user "$(id -u):$(id -g)": 由于容器默认用户为nonroot(id:65535),因此让容器内的进程以你当前主机的用户身份运行,从而解决挂载目录时的权限问题。
  • --port 8585 --disable-ip-origin-check: 这是追加传递给 hath-rust 程序的所有命令行参数,其他参数请看官方的参数列表或者使用参数-h;其中追加--disable-ip-origin-check参数是因为通过nginx代理以及docker的ip只有本地ip,不加这个参数会出错。-

若要限速,请参考以下步骤:

基本就是使用tc命令,我在这里使用tcconfig,能够简化操作。

#尽量不要在全局环境中安装pip包
python3 -m venv tcconfig
tcconfig/bin/pip install tcconfig

使用以下命令限制上传速度

sudo tcconfig/bin/tcset hath --docker --rate 10mbps

其中:

  • sudo tcset hath: tcsettcconfig 中用于设置规则的命令,hath 是目标容器的名称或ID。需要 sudo 权限来操作网络接口。
  • --docker: 明确告诉 tcconfig 目标是一个Docker容器,它会自动处理找到对应网络接口的逻辑。
  • --rate 10mbps: 这是核心的限速参数。它设置了出口带宽的上限。你可以使用不同的单位,常用的如下:
    • kbps: 千比特每秒
    • mbps: 兆比特每秒

使用以下命令检查规则,输出结果以json表示

sudo tcconfig/bin/tcshow hath --docker

注意:在运行这个命令后可能会出现以下错误

[ERROR] OperationalError: failed to execute query at /root/tcconfig/lib/python3.13/site-packages/simplesqlite/core.py(615) insert
  - query: INSERT INTO if_index(host,ifindex,ifname,"peer_ifindex") VALUES ('vps3149731',48,'veth1ea42e7',2)
  - msg:   UNIQUE constraint failed: if_index.peer_ifindex
  - db:    :memory:

这是因为不同容器之间的 peer_ifindex 可以相同导致的错误(来源),进入tcconfig的安装目录进行修改

# 根据自己python版本进行修改
cd tcconfig/lib/python3.13/site-packages/tcconfig
# 编辑_docker.py文件
vim _docker.py

找到peer_ifindex = Integer(not_null=True, unique=True)这一行,目前版本应该在33行。vim可直接使用斜杠(/)搜索这一行。

unique=True删掉,因此这一行修改为以下内容

peer_ifindex = Integer(not_null=True)

这样就不会出错了,能够正常施加限速。

本篇文章就是这样,欢迎多多评论,感谢指正。

咕咕咕~