我想要实现的是让 http(s) 请求源自机器A对于目标服务器来说,它似乎来自乙。
举个例子:
假设我有两个虚拟机A和乙运行 Ubuntu 并生活在同一个 VPN 中,机器上A有公网 IP1.1.1.1
和私网 IP 10.1.0.1
,而机器乙有公共 IP2.2.2.2
和私有 IP 10.1.0.2
,VPN 的 IP 范围是10.1.0.0/20
。
鉴于上述情况,我希望能够做到这一点:
ssh [email protected]
[email protected]:~# curl ifconfig.me
2.2.2.2
[email protected]:~#
请注意,我正在寻找解决方案仅限外向流量,我希望任何传入流量的路由都不会改变。
通过执行以下操作,我能够完成一半目标:
- 在机器上乙启用 IP 转发
sysctl -w net.ipv4.ip_forward=1
- 在机器上乙使用以下命令更新 iptables
iptables -t nat -A POSTROUTING -s 10.1.0.0/20 -o eth0 -j MASQUERADE
- 在机器上A使用以下方式更新路由
ip route change default via 10.1.0.2
然而,这种方法会阻断所有流量在直接1.1.1.1
包括ssh
,例如连接到1.1.1.1
我现在必须这样做,这对于我的用例是不可接受的。ssh -o ProxyCommand="ssh -W %h:%p [email protected]" [email protected]
我的理解是,通过iptables
在机器上使用A(而不是ip route change default ...
)我应该能够通过机器路由出站流量乙然而,到目前为止,我失败了。
我尝试过的一件事是使用机器更新OUTPUT
链条DNAT
A(带机器)乙设置如上所述),但这会导致所有请求超时。
ssh [email protected]
[email protected]:~# curl -m 5 ifconfig.me
1.1.1.1
[email protected]:~# iptables -t nat -A OUTPUT -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 10.1.0.2
[email protected]:~# curl -m 5 ifconfig.me
curl: (28) Failed to connect to ifconfig.me port 80: Connection timed out
尽管我并不执着于该iptables
解决方案,但如果可能的话,我还是希望避免需要下载非标准工具的解决方案。
如果有关系的话,我使用的特定平台是 Digital Ocean,因此虚拟机是 Droplets,VPN 就是所谓的虚拟私有云。
答案1
使用 MASQUERADE 设置进行 SSH 访问的最简单解决方案是添加端口转发规则2.2.2.2
:
iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 222 -j DNAT --to-destination 1.1.1.1:22
然后您就可以使用连接到。ssh -p 222 [email protected]
1.1.1.1
如果这个解决方案还不够,那么您需要一个更复杂的设置。
上述 MASQUERADE 解决方案由于 处的默认路由更改而中断了入站 SSH 连接1.1.1.1
。
在此设置中,SSH 连接的传入数据包来自面向 Internet 的接口。但是,1.1.1.1
通过 发送响应数据包2.2.2.2
,这会丢弃这些数据包,因为它们与连接无关。
为了解决这个问题,您需要标记属于 SSH 连接的数据包:
iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 22 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m connmark --mark 1 -j CONNMARK --restore-mark
iptables -t mangle -A POSTROUTING -m mark --mark 1 -j CONNMARK --save-mark
第一条规则将数据包标记 1 应用于所有发往 SSH 端口的数据包。
第二条规则将现有的连接标记恢复为数据包标记,以处理两个方向的路由。
第三条规则将现有的数据包标记保存为连接标记,以供以后的连接数据包使用。
下一步是为与 SSH 连接相关的数据包创建自定义路由表:
编辑/etc/iproute2/rt_tables
并添加以下行:
100 ssh
接下来,添加自定义路由表:
sudo ip rule add priority 1000 fwmark 0x1 table ssh
然后,向自定义路由表添加一条路由:
sudo ip route add table ssh 0.0.0.0/0 via <original default route> dev eth0 src 1.1.1.1