Ssh docker容器中基于端口的路由

Ssh docker容器中基于端口的路由,ssh,docker,iptables,Ssh,Docker,Iptables,我有一个docker应用程序容器(node:latestimage),它有两个网络接口: eth1:这是默认接口,是服务中所有容器之间的桥接网络。(由管道工程管理,但我无法更改该级别的任何内容) eth0:这是一个常规的docker0接口,可以访问除eth1之外的任何地方 下面是默认的路由表: Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Ifac

我有一个docker应用程序容器(
node:latest
image),它有两个网络接口:

  • eth1:这是默认接口,是服务中所有容器之间的桥接网络。(由管道工程管理,但我无法更改该级别的任何内容)
  • eth0:这是一个常规的
    docker0
    接口,可以访问除
    eth1
    之外的任何地方
下面是默认的路由表:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.25.88.254    0.0.0.0         UG    0      0        0 eth1
10.25.88.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
正如您所看到的,有必要将
eth1
作为默认接口,但这给我带来了一个问题:我的应用程序需要
ssh
访问其他一些远程服务器,这些服务器无法通过
eth1
访问,但
eth0
具有访问权限。因此,我需要更改此请求的路由。我的第一个解决方案是:

route add -net 10.20.33.0/24 gw 172.17.42.1
这种方法工作得很好,我可以访问范围
10.20.33.0/24
中的地址。但它会阻止这些主机对应用程序本身的访问。应用程序正在端口80上服务,添加此路由后,范围
10.20.33.0/24
内的主机向其发出的所有请求都将失败

所以我假设这个路由是全局性的,并且影响所有输入/输出请求到这个IP范围。我在stackoverflow上搜索了一种只路由输出ssh请求的方法,到目前为止,我得到的是:

# Initialize route table
echo 1 p.ssh > /etc/iproute2/rt_tables
ip route add table p.ssh default via 172.17.42.1

# Mark Packet with matching D.Port
iptables -A PREROUTING  -t mangle -p tcp --dport 22 -j MARK --set-mark 1
iptables -A POSTROUTING -t nat -o eth0 -p tcp --dport 22 -j SNAT --to 172.17.42.1


#IP Route
ip rule add fwmark 1 table p.ssh
ip route flush cache

#IP Stack
#This is the missing part from the guide
echo 1 > /proc/sys/net/ipv4/ip_forward
for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 0 > $f ; done
echo 0 > /proc/sys/net/ipv4/route/flush
但它不起作用。我已尝试通过
iptables
记录标记的包,因此我可能会在过程中发现任何问题,但
syslog
未在容器内运行,因此我安装了它
apt get install rsyslog
,并添加了以下规则:

iptables -A PREROUTING  -t mangle -p tcp --dport 22 -j LOG --log-level 4 --log-prefix "fwmark 1: "

但它也没有记录任何东西

几天后,我终于解决了这个问题。我使用如下
tcpdump
来确定流量是否通过
eth0
接口路由:

tcpdump -i eth0 port ssh
事实证明,第一个问题来自
iptables
标记命令。因此,我没有在
预路由
链上标记请求,而是在
输出
链上标记请求,如下所示:

iptables -t mangle -A OUTPUT -p tcp --dport 22 -j MARK --set-mark 1
现在我可以在
eth0
上看到ssh请求,但仍然无法连接。事实证明,这些请求需要伪装才能正常运行:

iptables --table nat --append POSTROUTING -o eth0 -p tcp --dport 22 -j MASQUERADE
最后的脚本现在类似于:

REMOTE_HOSTS=10.20.33.0/24
HOSTS_ADDR=172.17.42.1

# Add table
echo 1 p.ssh >> /etc/iproute2/rt_tables
# Add route
ip rule add fwmark 1 table p.ssh
ip route add $REMOTE_HOSTS via $HOSTS_ADDR dev eth0 table p.ssh

# Sets mark correctly
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j MARK --set-mark 1
iptables --table nat --append POSTROUTING -o eth0 -p tcp --dport 22 -j MASQUERADE

#IP Stack
echo 1 > /proc/sys/net/ipv4/ip_forward     # Default in debian/ubuntu
for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 0 > $f ; done

在仅为路由ssh设置iptables之后,是否删除了此路由:route add-net 10.20.33.0/24 gw 172.17.42.1?可能有助于解决您的问题。@ThanhNguyenVan是的,我已经删除了该路线,感谢您提供的链接,我已经尝试过了(回复的最后一条评论),但没有改变,问题仍然存在。