Routing Rules with VPN

Im newbie with this network things and need some help. I have setup like this

 ------------         ------------         ------------
|     A      |       |     B      |       |     C      | 
| 10.148.x.x |-------| 10.184.x.x |-------| 192.168.x.x|
|    APP     |       |    VPN     |       |   VPN      |
 ------------         ------------         ------------

I have a topology like this. Where B and C are connected as tunnel VPN site-to-site. I want to send traffic (e.g ICMP/API REQ/etc) from A to C through B and vice versa. Both A and C will received incoming traffic from B, not from real source (So, for example when C PING-ing B, B will direct that PING to A and tell A that the source of ping is from B). After surfing on many problems I found this rules works on me with IPTABLES and applied to B.

This is routing for A to C:

-A PREROUTING -s 10.148.x.x -d 10.184.x.x -p tcp/icmp -j DNAT --to-destination 192.168.x.x
-A FORWARD -s 10.148.x.x -d 192.168.x.x -p tcp/icmp -j ACCEPT
-A POSTROUTING -o eth0 -j MASQUERADE

This is routing for C to A:

-A PREROUTING -s 192.168.x.x -d 10.184.x.x -p tcp/icmp -j DNAT --to-destination 10.148.x.x
-A FORWARD -s 192.168.x.x -d 10.148.x.x -p tcp/icmp -j ACCEPT
-A POSTROUTING -o eth0 -j MASQUERADE

Its work great at common server but at this case:

I used TCPDUMP for dump the traffic at B. When C PING-ing B the traffic looks like

10:18:04.706713 IP 192.168.x.x > 10.184.x.x: ICMP echo request, id 49458, seq 12987, length 40
10:18:04.706806 IP 10.184.x.x > 10.148.x.x: ICMP echo request, id 49458, seq 12987, length 40
10:18:04.719587 IP 10.148.x.x > 10.184.x.x: ICMP echo reply, id 49458, seq 12987, length 40
this traffic direct to A but its seems like B cannot reply to 192.168.x.x

When A PING-ing B the traffic looks like the traffic return DUP!

64 bytes from 10.184.x.x: icmp_seq=1 ttl=187 time=48.1 ms
64 bytes from 10.184.x.x: icmp_seq=1 ttl=187 time=48.1 ms (DUP!)
64 bytes from 10.184.x.x: icmp_seq=1 ttl=187 time=48.2 ms (DUP!)
64 bytes from 10.184.x.x: icmp_seq=1 ttl=187 time=48.2 ms (DUP!)

from man ping:

Duplicate and Damaged Packets

ping will report duplicate and damaged packets. Duplicate packets should never occur, and seem to be caused by inappropriate link-level retransmissions. Duplicates may occur in many situations and are rarely (if ever) a good sign, although the presence of low levels of duplicates may not always be cause for alarm.

Damaged packets are obviously serious cause for alarm and often indicate broken hardware somewhere in the ping packet's path (in the network or in the hosts).

What did i missed?

EDITED: I'm so sorry if I'm not clear deliver the problem. Now I edited the IP, so the IP shown above all are Private IP instead of Public IP. There is no tunnel in A-B and tunnel VPN just between B-C. For this case, my user just want both A and C just hit and know IP B. Therefore, Either A and C just hit B.


You are making things way to complicated. In your setup, you are mapping the complete IP range 11.0.0.0/8 to 192.0.0.0/8 in one direction and in the other direction to 10.0.0.0/8. This implies that at site B, none of the 11.0.0.0/8 IPs will be reachable and directly useable.

First, 11.0.0.0/8 and 192.0.0.0/8 are public IP ranges which exists inside the internet, this is not meant for private use. How should your pc know if the public or the private ip is meant?

you should stick in your setup to the dedicated private ip ranges, which are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. These should be more than enough private ips, I doubt that you have 24 million devices at each site.

If I were you, I would setup the topology that the site-to-site VPN tunnel A-C is direct, so you have A-C and A-B as seperate tunnels. But there may be cases where this is not possible / wanted, I will assume that this is one of them. If I were you, I would setup the VPN tunnels with "visible" IPs:

The tunnel A-B is routing 192.0.0.0/8, with the tunnel endpoint inside B as gateway. B-C is routing 10.0.0.0/8 directly with tunnel endpoint inside B as gateway. That way, you do not have to mess with DNAT rules, all three IP ranges are fully useable and visible from all three sites. But please remember to change those subnets (for example to 10.1.0.0/16. 10.2.0.0/16 and 10.3.0.0/16)

[edit] And, if you really want to make your setup working, and set aside all warnings from my side: you need to remove the masquerade rule, and replace it with two SNAT rules. a MASQUERADE target replaces ALL source IPs with the IP of the gateway, making it impossible for the destination to know from which ip the request came from. This is obviously not what you wanted...

[edit2] Concerning the updated question:

a) "hide" the vpn behind B (the typical home office scenario) - this implies that the app cannot open an connection to C, C has to open the connection to A.

  • remove DNAT rule
  • modify MASQUERADE rule (you want to masquerade traffic only in one direction): -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth0 -j MASQUERADE

b) "publish" the routing connection to the whole app network: in this scenario, you will completely remove DNAT and MASQUERADE rules, and do it via routing: on site A) : route add -net 192.168.0.0/16 gw <place IP of B here>10.148.0.0

c) the virtual IP mapping scenario: The idea behind this scenario is to create a virtual IP, which is being used to access a server which stands in an private subnet not reachable otherwise. In this scenario, you need a full NAT (DNAT and SNAT) and an IP, which is not used anywhere. And plus, the correct routing needs to be in place, too... This is the most complicated scenario, since you are new to network things (as you say) I clearly discourage the usage of this solution.