443 端口共用方案 传递真实 IP 代理和后端在同一台服务器上

nginx作为tcp7层代理的时候并不是直接转发流量而是建立一个新的连接,而某些软件对7层的协议支持并不完整比如proxy_protocol 协议,导致显示的IP来源都是127.0.0.1或者干脆不能正常工作。所以我们现在要支持tcp 4层转发,让数据包直接去到后端。

我们可以在百度里看到各种文章,里面大部分都是在

stream {
    server {
       proxy_protocol on;#在这里加上这个配置

但是这个配置我觉得不是特别友好,特别是对于不支持7层的后端来说,你的来源全部都是127.0.0.1,很多分析无法进行。所以我们要用下面这个配置(一般在/etc/nginx/nginx.conf)

user root;#原来这里是www-data或者nginx的
worker_processes auto;

这些配置一般会跟你的ssl preread配置在一起

stream {
    server {
        listen 443;
        listen [::]:443;
		proxy_bind $remote_addr transparent; #加上这条

现在我们要创建IP透明代理路由。并且代理和后端要跑在一同台服务器上。如果你能看到这篇文章的话估计你已经找了很多类似文章了。通常文档都是介绍代理和后端不是在同一台服务器上的。

系统一般不允许将具有非本地源的数据包发送到环回地址,除非启用了route_localnet,如果具有环回地址的伪造数据包可能到达公共接口,这会产生安全问题。

但是这个限制仅适用于127/8地址范围,我们可以为环回接口分配别的的地址。从而绕过这个限制

ip addr add 192.168.127.1/24 dev lo scope host

debian系也可以在/etc/network/interfaces里改成这样。RH系很久没操作了,就用上面这个凑活吧,你们自己找持久化方法。

 auto lo lo:10
  iface lo inet loopback

iface lo:10 inet static
        address 192.168.127.40
        netmask 255.255.255.0
		network 192.168.127.0

这样,我们给回环地址分配一个192.168.127.40的地址和一个192.168.127.0/24的可达网段。

为了匹配返回数据包,我们需要查看OUTPUT链而不是PREROUTING链。

在不是同一主机的方案里,我们会用PREROUTING去匹配。就像别的教程里

iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100

但是,由于我们的流量来自本地主机,并且可以通过源地址轻松识别,因此我们可以放弃整个iptables匹配和基于标记的路由规则,将其替换为基于源的简单路由规则。

ip rule add from 192.168.127.0/24 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100

debian系可以用以下持久化方法

iface lo:10 inet static
        address 192.168.127.40
        netmask 255.255.255.0
		network 192.168.127.0
	up ip rule add from 192.168.127.0/24 lookup 100 #新增这两条1
	up ip route add local 0.0.0.0/0 dev lo table 100 #新增这两条2

然后可以nginx/trojan服务器行以连接到在此新地址范围上侦听的本地服务。
必须注意将环回接口用于透明代理连接,否则数据包将无法传递。 这是通过使用新的本地地址做为监听地址而不是*或者0.0.0.0来完成的。

nginx配置---stream部分

stream {
    根据sni分流
    map $ssl_preread_server_name $backend_name {
		yourname.com  trojan;
		default      web;
    }

    # web
    upstream web {
        server 192.168.127.40:444;
    }
    
    # trojan
    upstream trojan {
        server 192.168.127.40:445;
    }
    

    server {
        listen 443;
        listen [::]:443;
        proxy_pass  $backend_name;
        proxy_bind $remote_addr transparent;#4层转发模式
        ssl_preread on;
    }
}

nginx-server虚拟服务器部分,也就是你正常网站的部分

server {
    listen 444 http2 ssl;
	listen 192.168.127.40:444 http2 ssl;
    listen [::]:444 http2 ssl;
    server_name balabalayourname.com;
}

某些不能完整支持7层协议的软件,也一定要指定监听192.168.127.40或者特定IP,你指定*或者0.0.0.0是不管用的。

END

此条目发表在运维笔记分类目录。将固定链接加入收藏夹。

443 端口共用方案 传递真实 IP 代理和后端在同一台服务器上》有7条回应

  1. 欧文斯说:

    大部分主机会分配私有 IP,如 10.2.0.2 之类的,其实这个 IP 就可以当作是博主说的 192.168* 是吗?

  2. 欧文斯说:

    博主的评论配置是不是出故障了,提交了三次,第一要我返回重新提交,第二次提示没填验证码(实际上没有弹出要填),第三次提示已经评论过了。。。

  3. 欧文斯说:

    其实我还是不太懂博主的意思,以 Tj 为例,把 Tj 作为前端,是可以获取到 IP 的,当不匹配时 Tj 会路由至后端网站,这时后端网站获取到的 IP 是 127.0.0.1 而不是真实 IP,博主文章是解决这个问题吗?

  4. 欧文斯说:

    因为按照博主的配置,路由至 Tj 后,Tj 没有匹配成功,会再路由到真实网站,此时真实网站获取到的仍然是本地地址

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据