1

since I am fairly new to networking in general, but need to implement a specific scenario I would like to ask for support. Thanks for everything in advance.

I have a following scenario, on my machine A I have a software running which is usually connected to machine B via an ethernet cable. What I would like to do now is to connect to machine B remotely via an in-between router/device from machine A, lets call this new device machine C. I believe that I will need to work with IP routing using iptables.

Note: machine A is not in the same subnet as machine B

So the scenario will look like this:

  192.168.20.X machine A 10.8.0.55  <--tap0--> 10.8.0.50 machine C 192.168.27.1 <--eth0--> 192.168.27.100 machine B

How I believe iptables will do the job:

So for example when machine A would like to connect to machine B it has to connect with its tap0 interface using 10.8.0.50:12345. Machine C will alter the IP packets (via iptables) from tap0 and send it to its eth0 connection using the same port 192.X.X:12345. Machine B will reply to machine C, which is then sending it back to machine A.

So some of my questions are:

  1. If machine C is unaware of machine B's ip address, but I know it is connected with its eth0 interface, can I still route traffic to its eth0 ip address under the condition that machine A is sending packets destined to machine B? For example using the gateway tap0?
  2. If machine A and C are unaware of machine B's ip address, is it possible to route traffic to B's eth0 ip address? Or would that packet be discarded because it doesnt contain the destination IP address?
  3. Can I forward packets in machine C to different interfaces and keep the same ports?

I was following this guide without implementing the firewall rules, but I was unable to connect properly because it was using hardcoded IP address which I would like to avoid, I would like to forward the traffic from tap0 to eth0 in machine C and in best case not need to know machine B's ip address.

I was trying to use these rules in machine C but to be honest I am not understanding them very well.

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE  
sudo iptables -A FORWARD -i eth0 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT

If you could reference me to some easy to understand resources, I would check them out as well. Thank you.

Also checked out:

this question this question


EDIT: I have added a simplified layout of the scenario. I was figuring out that I possible need to use NAT.

From machine A I tried to send packets to machine C using ping 10.8.0.50 where machine B has ip address: 192.168.27.106. When I send packets from machine A to C I want it to change the packets source and destination address, so I've applied:

sudo iptables -t nat -A PREROUTING -i tap0 -j DNAT --to 192.168.27.100
sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 10.8.0.55

Using sudo tcpdump -i eth0 on machine B I got a correct ICMP request. However, the echo didnt go back to machine A. Naturally I thought I'd need to apply the iptables rule back again to machine A. So I've applied:

sudo iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 10.8.0.55
sudo iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to 192.168.27.100

I was able to send the packets through to machine B, but didnt get the reply back to A. I feel like something is missing. Any ideas?

enter image description here

V.Hunon
  • 111
  • 1
  • 3
  • Do you need network address translation (NAT) at all? – Mathias Weidner Mar 10 '21 at 16:23
  • How could I accomplish in any other way? With static route? – V.Hunon Mar 11 '21 at 08:12
  • Yes, your task is usually done with routing and packet forwarding. NAT is only needed when some addresses are not routable. In your case machine C needs two addresses, one in the same network as machine A and one in the same network as machine B. Machine A and B need a route to each other that points to machine C, which does the packet forwarding. – Mathias Weidner Mar 11 '21 at 09:12
  • @MathiasWeidner Machine C has not the ability to be on the same subnet. Machine C has only one address and can not be changed. I was thinking about to set up iptables on machine B to do DNAT to alter the packets target destination (which is machine B's IP) and second to do SNAT, to alter its source IP address. That way, machine A's packet can reach machine C. But right now I am failing to run it. – V.Hunon Mar 11 '21 at 13:00
  • Can you please provide a clean diagram containing the machines, the connected interfaces and their respective addresses. – Mathias Weidner Mar 11 '21 at 13:55
  • @MathiasWeidner I have added a simplified layout for more clearity. – V.Hunon Mar 11 '21 at 16:02
  • What is the connection between machine A and machine C? In your image you named the interfaces tap0 which would point to a virtual network device, but you added a symbol usually taken for WiFi devices. – Mathias Weidner Mar 12 '21 at 13:56
  • @MathiasWeidner it is just a virtual network adapter tap0. I used a WiFi symbol because it should "show" that it is completely remote. But it could be a WiFi as well - tbh it doesnt matter. – V.Hunon Mar 12 '21 at 14:01

2 Answers2

1

Machine C has only one address and can not be changed. - but on your picture it has 2 addresses in both A and B subnetworks and 2 network interfaces tap0 and eth0.

Also, your picture and your text for IPs differs. What is 192.168.27.106 really? Machine B IP on the eth0? But your picture shows it's as 192.168.27.100. You are doing SNAT to 10.8.0.55, but that's a Machine A IP according to your picture. That way the Machine C will send ICMP reply to that IP according to it's routing table. You need to SNAT to your Machine B IP on the eth0 side, i.e. 192.168.27.1 if your picture has correct IPs noted. I.e. something like this:

sudo iptables -t nat -A PREROUTING -i tap0 -j DNAT --to 192.168.27.100
sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 192.168.27.1

You don't usually need a "reverse" NAT rules, as conntracking should resolve it back again on remembered packets.

NStorm
  • 1,312
  • 7
  • 18
  • My bad, you are right. I accidentally mistyped a wrong IP. Machine C is the "middle man" it has indeed 2 IP address'. Machine B is the target machine and has only 1 IP address, which is connected with the eth0 from machine C it has the 192.168.27.100 address. In my iptables I meant of course 192.168.27.100. I will update it accordingly. Do I need to enable conntracking manually? I will try out your solution and come back to you. Question here, if machine B replies back to machine C. Will this ICMP packet come back to machine A? What about if I want to acces machine C's ports? – V.Hunon Mar 12 '21 at 08:26
  • sorry that I come back to you several days later. Your solution works as a charm. I was able to connect to my other device with my program, even the ports are used properly. So when I connect from machine A to C with 10.8.0.50:5555 I will directly get connected to 192.168.27.100:5555 on machine B. Thanks! Is it possible to to SNAT, DNAT without knowing machine B's IP address? for example to do the routing on any device which is connected to eth0 on machine C? – V.Hunon Mar 15 '21 at 08:08
  • @V.Hunon glad it worked for you. If this solves your issue, please upvote & accept the answer. Answering your comment - no, you can't. The DNAT is the Destination NAT. It works by changing the destination IP address in the packets. And you have to know the IP you want to change it to. It can't just magically guess it as theoretically there might be any count of hosts behind your connection. While you know it's directly cable connected to only one host, it's not obvious for the machine. – NStorm Mar 15 '21 at 14:47
  • But you can write some scripts to guess/find required destination IPs and then set DNAT to it. How you do it is usually depends on your setup. But this out of scope for this question. – NStorm Mar 15 '21 at 14:48
0

Given the topology in the picture you can connect machine A with machine B solely with routing and packet forwarding.

On machine A you add a route to B via machine C like this:

ip route add 192.168.27.100/32 via 10.8.0.50

On machine B you add a route to A via machine C like this

ip route add 10.8.0.55/32 via 192.168.27.1

On machine C you activate IP forwarding with

/sbin/sysctl -w net.ipv4.ip_forward=1

Normally there is no iptables necessary, you can reach machine A and B with their respective adresses.


If you can't add the routing entries at machine A and machine B, you have to use machine C as a proxy for the other side of the connection and configure NAT on machine C.

NAT is disruptive and can break things in unexpected ways. Therefore I recommend to make the NAT rules as specific as possible and document why the NAT was necessary.

You can use the NAT rules that NStorm provided in the other answer to make it "general":

sudo iptables -t nat -A PREROUTING -i tap0 -j DNAT --to 192.168.27.100
sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 192.168.27.1

But please keep in mind, that with these rules you can't access machine C anymore from any network that's coming in at interface tap0. Therefore I would recommend to limit the NAT to only the necessary ports, protocols and source addresses.

Mathias Weidner
  • 417
  • 3
  • 10
  • Thanks for your answer. I am not allowed/able to change settings on machine A and B so I can not add a route like you mentioned. – V.Hunon Mar 15 '21 at 07:24
  • Do you know the protocol and port number that you want to reach at machine B? – Mathias Weidner Mar 15 '21 at 11:59
  • Usually yes but not always. I would like to keep it as general as possible. I cant edit any settings on machine A nor B. So adding a gateway on machine A or similar does not work. I can only do something on machine C. However, machine A needs to connect to a specific IP and port, because of this i need to manually input ip and port on an application on machine A. – V.Hunon Mar 15 '21 at 13:16