Server Fault Asked by mkopriva on December 9, 2021
What I’m trying to achieve is to have http(s) requests originating from
machine A appear to the target server to be coming from machine B.
To illustrate with an example:
Let’s say I have two VMs A and B running Ubuntu and living in the same VPN, machine A has public ip 1.1.1.1
and private ip 10.1.0.1
while machine B has public ip 2.2.2.2
and private ip 10.1.0.2
, the VPN’s ip range is 10.1.0.0/20
.
Given the above I would like to be able to do this:
ssh [email protected]
[email protected]:~# curl ifconfig.me
2.2.2.2
[email protected]:~#
Note that I’m looking for a solution to route only outgoing traffic, I would like the routing of any incoming traffic to not be altered.
I was able to get halfway there by doing the following:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 10.1.0.0/20 -o eth0 -j MASQUERADE
ip route change default via 10.1.0.2
However this approach breaks all traffic coming in directly to 1.1.1.1
including ssh
, e.g.
to connect to 1.1.1.1
I would now have to do this ssh -o ProxyCommand="ssh -W %h:%p [email protected]" [email protected]
, which is not acceptable for my use case.
It is my understanding that by using iptables
on machine A (rather than ip route change default ...
) I should be able to route outging traffic through machine B, however, so far, I’ve failed.
One of the things that I’ve tried is updating the OUTPUT
chain with DNAT
on machine A (with machine B setup as above) but that causes any and all requests to time out.
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
While I’m not wedded to the iptables
solution I would like to avoid, if possible, solutions that require the download of non-standard tools.
In case it matters, the specific platform I’m using is Digital Ocean, so the VMs are Droplets
and the VPN is what they call Virtual Private Cloud.
Easiest solution for the SSH access with MASQUERADE setup is to add a port forwarding rule on 2.2.2.2
:
iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 222 -j DNAT --to-destination 1.1.1.1:22
Then you can use ssh -p 222 [email protected]
to connect to 1.1.1.1
.
If this solution is not enough, then you need a more complex setup.
The MASQUERADE solution above breaks inbound SSH connectivity because of the default route change at 1.1.1.1
.
In this setup incoming packets for the SSH connection come from Internet facing interface. However, 1.1.1.1
sends response packets via 2.2.2.2
, which drops them since they are not associated with a connection.
To work around this, you need to mark the packets belonging to the SSH connection:
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
First rule applies packet mark 1 to all packets that are destined to SSH port.
Second rule restores existing connection marks to packet marks to handle routing for both directions.
Third rule saves existing packet mark to connection mark for later connection packets.
Next step is to create a custom routing table for packets related to SSH connections:
Edit /etc/iproute2/rt_tables
and add the following line:
100 ssh
Next, add a custom routing table:
sudo ip rule add priority 1000 fwmark 0x1 table ssh
Then, add a route to the custom routing table:
sudo ip route add table ssh 0.0.0.0/0 via <original default route> dev eth0 src 1.1.1.1
Answered by Tero Kilkanen on December 9, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP