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

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

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

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

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

user root;#原来这里是www-data或者nginx的
worker_processes auto;
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

发表评论

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

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