📜 ⬆️ ⬇️

Combining two local area networks with the same network numbers on a Linux gateway

When creating a local network, not every administrator is responsible for choosing a range of addresses. Or maybe not everyone guesses about the presence of private ranges except for 192.168.0.0/24. And over time, such a time bomb can make itself felt. Local networks are combined, there is a need for communication between the hosts of different networks. And here it turns out that the numbers of the networks are the same. And to change them for some reason is problematic or impossible.

In this case, the server routing the packets between the networks is left to pretend that the network numbers are different and wishful thinking. In the rich arsenal of Linux there are tools for such manipulations: iptables with NETMAP and the ip utility.

purpose


From LAN1 we want to send a packet to LAN2. But we can not send it to the network, the number of which is the same with ours. In the most frequent case, 192.168.0.0/24. If such a package appears in LAN1, he will not know what LAN2 is, he will look for such a machine in LAN1. These are the default routing rules.
So, you need to send packets with other addresses that will go to the router.

How it should look for the observer from LAN1
For example, the user of the LAN1 network will see the LAN2 network as 10.8.1.0/24. There is already no intersection of addresses. LAN1 satisfied.
')
What it looks like on both sides
A packet arrives from LAN1 with the sender address 192.168.0.100 and the destination address 10.8.1.200. From the router from the LAN2 interface comes the same packet with the source address 10.8.1.100 and the destination address 192.168.0.200. The package passes to the destination address and sends it in response to the sender's address with its address. The package goes to the router. In it, the inverse transform occurs and the user LAN1 receives a response from the address to which he sent the packet.
image

Theory. Path package in the core of the router: netfilter


Here I will try to talk about the journey of transit traffic through our Linux router. For a complete understanding of the package travel process, it is better to see the scheme of its passage from Wikipedia through netfilter chains.
image
Our package with [source | destination] [192.168.0.100 | 10.8.1.200] falls on the network interface of the router and its first chain is PREROUTING.

PREROUTING

Passing through the chain, it enters the PREROUTING mangle table. In which, using iptables, we define the interface from which it came, and the source address. If this is our patient, we mark him with a MARK.
After that the package [192.168.0.100 | 10.8.1.200 | (marked)] falls into the nat table. This table is for address translation. Since there is no real address 10.8.1.200, at the next stage of routing the packet will be dropped or left in an unknown direction. Therefore, we replace his destination address with the one to which he really should go exactly here: [192.168.0.100 | 192.168.0.200 | (marked)]. This is done by the action NETMAP, which replaces the network number by mask.

ROUTING

Our package enters the decision-making stage, where it should go further. It is marked, so we can send it to a special routing table that we created for this case. It decides that the package is not intended for the local computer and must go to LAN2.

The package successfully passes the FORWARDING chain. Falls back to the routing stage. If in FORWARDING nothing happened to him, but in theory it should not have been. He goes the same way. Then it gets into POSTROUTING.

POSTROUTING

Unchanged reaching the table nat. We need to change the source address. After all, the answer to the packet [192.168.0.100 | 192.168.0.200] will be sent to the local network, and not to the router. So that he got back to the router, change the source address to a nonexistent [10.8.1.100 | 192.168.0.200]. Again NETMAP. After that, the package goes to LAN2.
With the return package, we perform the reverse procedure so that it reaches the original source.

Implementation


iptables -t mangle -A PREROUTING -i tun0 -d 10.8.1.0/24 -j MARK --set-mark 8 

We mark incoming packets on our non-existent network for further identification in netfilter. You can do without tags, use the source address, the input interface and the destination address as criteria, but in the case of complex routing with individual routing tables, deciding where to send the packet will be easiest for the label.
 iptables -t nat -A PREROUTING -m mark --mark 8 -j NETMAP --to 192.168.0.0/24 

We recognize the packet by the label and the action NETMAP in the PREROUTING table replaces the network number.
 iptables -t nat -A POSTROUTING -m mark --mark 8 -j NETMAP --to 10.8.2.0/24 

In POSTROUTING, NETMAP replaces the source address.
After that, all calls to the subnet 10.8.1.0/24 will look inside LAN2, like calls from the subnet 10.8.2.0/24.

ROUTING

To route packets by tag, you need to create your own routing table. Let's edit / etc / iproute2 / rt_tables, adding a unique number and the name of the new table.
256 netmap
Next, you need to add a rule according to which packets for routing will be sent to this table.
 ip ru add fwmark 8 lookup netmap 

Now marked packets will go to the routing netmap table.

And the last step is to determine the routes in the netmap table.
 ip route add default dev eth1 table netmap 

Or you can specify in a special case a separate gateway, if traffic to the network from the router goes through it. Something in the spirit of:
 ip route add default via 192.168.1.254 dev eth1 table netmap 

It is too early to rejoice, the answer will come to us from LAN2 [192.168.0.100 | 10.8.2.200].
We must do the same thing, but only convert back. Alas, netfilter itself does not. All actions have already been described, I will give only a sequence of commands for converting addresses into one and in the opposite direction. (In the first routing table there is no need in this case, but in other circumstances it may be necessary.)
 ip rule add fwmark 8 lookup netmap ip route add 192.168.0.0/24 dev eth1 table netmap iptables -t mangle -A PREROUTING -i tun0 -d 10.8.1.0/24 -j MARK --set-mark 8 iptables -t nat -A PREROUTING -m mark --mark 8 -j NETMAP --to 192.168.0.0/24 iptables -t nat -A POSTROUTING -m mark --mark 8 -j NETMAP --to 10.8.2.0/24 #    ip rule add fwmark 9 lookup netmap2 ip route add 192.168.0.0/24 dev tun0 table netmap2 iptables -t mangle -A PREROUTING -i eth1 -d 10.8.2.0/24 -j MARK --set-mark 9 iptables -t nat -A PREROUTING -m mark --mark 9 -j NETMAP --to 192.168.0.0/24 iptables -t nat -A POSTROUTING -m mark --mark 9 -j NETMAP --to 10.8.1.0/24 


results


Here is what tcpdump writes (first example with vnc, second with ping):
 tcpdump -i any port 5900 

12:46:46.358969 IP 192.168.0.100.41930 > 10.8.1.200.5900: Flags [P.], seq 647:657, ack 261127, win 1213, options [nop,nop,TS val 460624 ecr 171318], length 10
12:46:46.358978 IP 10.8.2.100.41930 > 192.168.0.200.5900: Flags [P.], seq 647:657, ack 261127, win 1213, options [nop,nop,TS val 460624 ecr 171318], length 10
12:46:46.505847 IP 192.168.0.200.5900 > 10.8.2.100.41930: Flags [.], ack 657, win 64879, options [nop,nop,TS val 171320 ecr 460624], length 0
12:46:46.505861 IP 10.8.1.200.5900 > 192.168.0.100.41930: Flags [.], ack 657, win 64879, options [nop,nop,TS val 171320 ecr 460624], length 0


 tcpdump -i any icmp 

12:47:46.363905 IP 192.168.0.100 > 10.8.1.200: ICMP echo request, id 2111, seq 1, length 64
12:47:46.363922 IP 10.8.2.100 > 192.168.0.200: ICMP echo request, id 2111, seq 1, length 64
12:47:46.364049 IP 192.168.0.200 > 10.8.2.100: ICMP echo reply, id 2111, seq 1, length 64
12:47:46.364054 IP 10.8.1.200 > 192.168.0.100: ICMP echo reply, id 2111, seq 1, length 64


Tcpdump perfectly demonstrates how addresses are transformed at the input to one interface and at the output to the other and in the opposite direction.

Other services, such as Samba and its equivalent on Windows, also work fine.

Note

If the connection between the networks is organized through the OpenVPN tunnel, then in order to correctly route from the client side, an additional route through the tunnel must be added to the server config.
push "route 10.8.1.0 255.255.255.0"

Warning!

When debugging a configuration, do not try to connect to the server on which the gateway is. Connect to the machines behind him in LAN2.
And that's why. The rules are calculated that the packet will pass through the gateway, ie
PREROUTING -> Routing -> FORWARD -> Routing -> POSTROUTING
If the packets are addressed to 10.8.2.1 (to the server), then as a result of routing they will go to the INPUT chain and the source address will not be converted to POSTROUTING.
PREROUTING -> Routing -> INPUT -> Application
Accordingly, the source address will not be changed and the response will be sent not to 10.8.2.xy, but to 192.168.0.xy - to the default route for this range, that is, to LAN2, and not to LAN1.

Source: https://habr.com/ru/post/117320/


All Articles