荣耀之链论坛

 找回密码
 立即注册
搜索
查看: 783|回复: 2

haproxy透传IP教程

[复制链接]

1326

主题

2373

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
10267
发表于 2022-8-27 00:31 | 显示全部楼层 |阅读模式
https://www.jianshu.com/p/e3d3ba76badc

我安装了rockylinux
WAN口IP是192.168.11.22 LAN口IP是192.168.0.2
然后用命令安装yum install haproxy
haproxy -v查看版本号是HA-Proxy version 1.8.27-493ce0b 2020/11/06
然后
我按照教程里面的写法配置了haproxy和iptables  我配置的是22端口
成功
haproxy配置如下:
listen ssh01
        bind 192.168.11.22:2200
        mode tcp
        maxconn 2000 #这隔是最多连接数
        source 0.0.0.0 usesrc clientip #这个是开启透传的语句,就这样写
        timeout server 60s #这3个延迟是指定时间内没有数据包交流就断掉,根据需要调节吧
        timeout client 60s
        timeout connect 60s
        balance roundrobin
        server ssh_1 192.168.0.2:22 check inter 5000 fall 1 rise 2

iptables配置如下:
iptables -t mangle -I PREROUTING 1 -p tcp -m socket -j MARK --set-mark 1

路由规则添加:
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100

最后提供ssh的服务器192.168.0.2配置网关,或者手动添加路由表
route add -net 0.0.0.0/0 gw 192.168.0.1  #这个网关就是ha服务器的LAN口地址

然后我自己的电脑ip是192.168.11.179访问192.168.11.22:2200就好了
在ssh服务器用netstat -ant命令查看链接发现就是能正常显示客户端IP的
tcp        0      0 192.168.0.2:22          192.168.11.179:51584    ESTABLISHED


需要注意的点是ha服务器的firewall不能开启masquerade,否则透传绝对失败,这个坑一定要注意


目前还有个小问题:如果后端服务器同时也需要上网,这个要怎么办呢? 如果haproxy服务器开启了转发就不能正常透传了   阿里云也不知道是怎么做到的


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

1326

主题

2373

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
10267
 楼主| 发表于 2022-8-27 00:53 | 显示全部楼层
  1. /sbin/haproxy -f /etc/haproxy/3306haproxy.cfg &
  2. /sbin/haproxy -f /etc/haproxy/2200haproxy.cfg &
  3. /sbin/haproxy -f /etc/haproxy/80haproxy.cfg &

  4. /sbin/iptables -t mangle -I PREROUTING 1 -p tcp -m socket -j MARK --set-mark 1

  5. /sbin/ip rule add fwmark 1 lookup 100
  6. /sbin/ip route add local 0.0.0.0/0 dev lo table 100
复制代码


启动项脚本里面这样写 前4句没效果 估计还是要手动

回复 支持 反对

使用道具 举报

1326

主题

2373

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
10267
 楼主| 发表于 2022-9-7 14:28 | 显示全部楼层
对一楼的补充
下面是我的研究过程,可以看看,结论我放到最下面用红字隔开了

如果内部的服务器也需要上网,则可以开启转发
第一种:永久开启转发,防火墙重启也有效
打开/etc/sysctl.conf 文件,在文件中添加如下配置:
net.ipv4.ip_forward = 1
然后输入命令sysctl -p使之生效

第二种:临时开启转发,防火墙重启以后就失效了
echo 1 > /proc/sys/net/ipv4/ip_forward

然后防火墙添加一条NAT规则
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE
这条规则一定要指明源地址 表示是单向的
或者不写源地址,而是只指定接口,在只有一个LAN口一个WAN口的防火墙上效果一样的,只有在有多个LAN口和一个WAN口的情况下,才建议只指定接口

为了严谨,可以同时指定源地址和接口
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE


然后测试添加一条端口转发规则看看是否有效果
iptables -t nat -A PREROUTING -p tcp --dport 2201 -j DNAT --to 192.168.0.2:22
实测能转发,并且在服务器上看到的连接IP也是外面的IP
但是在防火墙上通过netstat -ant命令,看不到连接
注意:这个端口转发就不能添加2200端口的转发了,否则会失效


再次测试在FORWARD链里面屏蔽11.179访问2200端口
貌似这个代理并没有通过FORWARD链,所以屏蔽2200没用
如果屏蔽2201呢 试试看
屏蔽2201也没用,这个时候在防火墙netstat -ant看不到连接 在服务器能看到正常的外面IP的连接
这是什么原理?
我大概懂了,因为我们在mangle表的PREROUTING链里面添加了规则,给数据包打标了
然后数据包就直接转发了,没有经过nat表(这个结论是错的)

测试iptables的mangle表 指定接口试试
iptables -t mangle -I PREROUTING 1 -i eth1 -p tcp -m socket -j MARK --set-mark 1
打标必须指定LAN口的那个接口,这样指定以后删除其他打标规则,可以正常透传

原理的理解:
一:外面的用户访问防火墙的2200端口
haproxy监听2200端口,转发给内部服务器的22端口
外网的数据包到达防火墙的WAN口然后通过haproxy直接转发给内部服务器的22端口(不改变数据包),这个时候会记录连接的发起端口假设是4567
内部服务器接受到数据包,然后返回一个数据包,这个数据包返回给防火墙的LAN口,防火墙接受到这个数据包以后直接打标,这个打标的数据包可以路由,然后再把这个数据包发出去,发出去查看到之前记录的连接的信息,就把这个数据包发给客户端的4567端口
这样就构成了一个完整的路径

这个时候防火墙是没有开启转发的
二:服务器自主的发起访问外网的请求
数据包到达防火墙LAN口
防火墙给这个数据包打标
防火墙把数据包发出去(这个时候防火墙会使用一个端口给这个连接假设就是3456吧,这个端口不会是2200)以后,外网的服务器返回的数据包返回给防火墙的3456端口,防火墙一看,你发给我的这个数据包是给我的3456端口,但是我在这个端口并没有提供任何服务啊,就丢弃了
这个时候的表现就是服务器能正常在22端口提供服务,但是服务器不能访问外网

三:下面再看看防火墙添加了转发以后的效果
服务器产生一个访问外网的数据包
数据包到达防火墙LAN口
防火墙给这个数据包打标
防火墙把数据包发出去(这个时候防火墙会使用一个端口给这个连接假设就是3456吧,这个端口不会是2200)(同时由于开启了转发,防火墙会记录这条连接)以后,外网的服务器返回的数据包返回给防火墙的3456端口,防火墙一看,你发给我的这个数据包是给我的3456端口,虽然我在这个端口并没有提供任何服务,但是我刚才记录了一条转发记录,3456端口的数据包要转发给内部的那台服务器,就正常的转发
这个时候的表现就是服务器能访问外网
最后再看看防火墙添加一条2201端口映射以后外面的客户端访问的效果
首先外面的客户端访问2201
防火墙把数据包转发给服务器,但是应该是通过LAN口转发的
服务器接受到这个数据包,然后返回

在/proc/net/nf_conntrack里面能看到这样一条记录
src=192.168.11.179 dst=192.168.11.22 sport=61111 dport=2201 src=192.168.0.2 dst=192.168.11.179 sport=22 dport=61111


卧槽,什么鬼,我把haproxy关了,但是在服务器上看到的还是外网IP啊
我看看我那台服务器是什么效果
ESTABLISHED src=183.93.122.254 dst=59.56.111.225 sport=3715 dport=12201 src=192.168.86.3 dst=192.168.86.253 sport=22 dport=3715
我那台托管的服务器的记录是这样的,可以看到后面的就是服务器的LAN口地址192.168.86.253

那是否说明只需要打标的几条命令就可以了,其实不需要haproxy
一会试试
目前服务器已经默认开启了转发mangle表添加好了
ip rule
ip route都添加好了
然后添加端口转发
iptables -t nat -A PREROUTING -p tcp --dport 2201 -j DNAT --to 192.168.0.2:22
实测能看到真实IP

如果不打标呢?
iptables -t mangle -D PREROUTING 1
ip rule del fwmark 1 lookup 100

不打标,只开启转发然后端口映射
可以显示真实IP
但是服务器无法访问外网(这个时候服务器的网关是设置好的)

然后增加POSTROUTING规则
但是增加的时候有条件
如果什么条件都不写,直接开启NAT
iptables -t nat -A POSTROUTING -j MASQUERADE
这个就是在所有接口上都开NAT,这样的话外面的客户端访问服务器,服务器看到的IP就是防火墙的LAN口地址,不要这样
正确的做法是指定源地址和出口接口
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
这样就表示只有服务器访问外网的时候才NAT,而外面访问服务器不NAT
另外这个命令的前提是服务器的网关指向防火墙
(这条命令可以扩展,比如我只允许内部的部分客户端可以访问外网,这样的效果和FORWARD允许还是有部分区别的)
(另外刚刚才明白FORWARD链的生效规则,按照这样指定源地址和接口的转发以后FORWARD链添加屏蔽规则的时候应该指定内部服务器的端口
比如 iptables -A FORWARD -s 192.168.0.2 -p tcp --sport 22 -j DROP这样添加规则,才表示服务器的22端口禁止访问,千万不要写映射的端口,比如这里的例子的2201,没用的,这样添加了规则外面的客户端访问防火墙的2201端口并不经过FORWARD链)
上面的阻断是数据包能到达服务器,如果不希望数据包到达服务器可以用这样的语句iptables -A FORWARD -d 192.168.0.2 -p tcp --dport 22 -j DROP

测试服务器不设置网关试试
实测服务器不设置网关端口映射失败
必须再添加一条iptables -t nat -I POSTROUTING 1 -o eth1 -j MASQUERADE
让外面的访问里面的也NAT才行
这个时候POSTROUTING有2条,其实就是双向NAT了
卧槽,我发现我一直以来都是双向NAT在用
双向NAT的好处是防火墙两侧的设备,只要能访问他们各自那一侧防火墙的接口,就可以顺利的互相转发
单向NAT就是指允许一方访问另一方,反之则不行
而不开NAT就表示不允许互访,但是如果开了端口映射还是能访问端口的




#####################################################

上面的一些文字是我研究的过程,里面有些错误,可以看看
现在结论我放到下面

首先:
haproxy这个软件最好只用来负载均衡,透传并不是他的主要作用
另外透传也不需要给数据包打标,网上的一些教程纯属误导人

然后:
我重新认识了iptables
转发 POSTROUTING PREROUTING 这3个地方的功能不一样
转发就是单纯的路由
POSTROUTING主要是地址伪装,也就是NAT
PREROUTING主要是端口映射
这3个东西可以结合使用
单独开转发仅仅只是让防火墙能转发数据包,要实现其他功能还需要其他操作
开转发,同时服务器设置了网关,然后防火墙设置PREROUTING端口映射就可以实现IP透传 这个时候服务器是不能上网的
开转发,同时服务器设置了网关,然后防火墙设置单接口POSTROUTING 就能让服务器访问外网 之后如果防火墙设置PREROUTING端口映射也能实现IP透传
开转发,服务器不设置网关,然后防火墙设置全接口POSTROUTING 然后防火墙设置PREROUTING端口映射 就可以让外面的客户端访问服务器被映射的端口,这个时候服务器看到的IP就是防火墙的LAN口IP

FORWARD在PREROUTING之后
数据包进来先匹配PREROUTING,如果匹配了就进入FORWARD如果不匹配就进入INPUT

最后放上iptables开启IP透传的教程
第一步:开启转发
第二步:PREROUTING开启端口映射
第三步:内部服务器的网关指向防火墙的LAN口
仅仅这3步就可以了
效果就是服务器通过netstat -ant命令看到的IP是客户端的真实IP

如果这个时候还需要服务器能上网,则只需要把服务器的IP增加到POSTROUTING里面
比如iptables -t nat -A POSTROUTING -s 192.168.0.2 -o eth0 -j MASQUERADE




回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

荣耀之链

GMT+8, 2025-6-18 16:39 , Processed in 0.014126 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表