1

I have a server with 1 interface bridged to tap0. Also a client with 2 interfaces that have public Internet connection (eth1 and eth2) and a tunnel for interface 2, so I can send traffic through tap0 and will actually send data through eth2.

if I do

curl ifconfig.co

I get the public IP of eth1. If I do

curl ifconfig.co --interface eth2

I get the public IP of eth2, and if I do

curl ifconfig.co --interface tap0

I get the public IP of the server (it went through the tunnel, so everything is fine).

tap0 is in 192.168.0.0/24 subnet (the other ones are 192.168.1.0/24 and 192.168.3.0/24, so no conflict here) and I can connect correctly to 192.168.0.1, 192.168.0.22 (which is the server local IP) and etc.

I have set in the server router (192.168.0.1) a redirection for the ports I need to the machine at 192.168.0.22 (iperf3, 80, OpenVPN and such).

In short, I think that I have everything working correctly up to this point.

The problem comes when I want to connect to the server public IP. Lets say the public IP is 1.2.3.4 through the VPN. If I do

curl 1.2.3.4

I get all the info I need, as the connection goes through eth1 to the server router, which redirects it to the local machine where the server sits. But if I do

curl 1.2.3.4 --interface tap0

NOTHING HAPPENS!

Checking client tap0 with tcpdump I can see that a request is created enter image description here
But that request never reaches tap0 on the server (checked eth0 on the server for incoming OpenVPN UDP packets and no new packets arrive when this one is created in client tap0). This is eth0 on the server when connecting to whatever else from client: enter image description here
This becomes a decrypted packet on tap0 and needless to say that no decrypted packet appears on tap0 when no UDP packet appears there.

I don't know what is happening here. I thought that all packets that go through tap0 on the client will be sent to the server, without limitations, but this don't seem the case.

Also, if I go to the server machine 192.168.0.22 and do a curl to the public IP, I get a connect back to the web server and curl receives the result, so the server don't has problems connecting to itself.

Diagram (Don't kill me): enter image description here

What can I do so connections to my server public IP works when sent over tap0?

2 Answers2

0

First you must accept that for the VPN to stay connected connections from the VPN client to the VPN server must happen outside of the VPN.

Second you have to understand that curl 1.2.3.4 --interface tap0 doesn't change anything about routing on your client. All it does is control what the source IP of the packet will be. If you connect to the external IP of the VPN server it is still going to go out directly, and not magically get sucked into the tunnel.

Anyway look closely at your routing table, that tells you how packets will flow.

What can I do so connections to my server public IP works when sent over tap0?

Standard answer: you don't. Use split DNS or something else so when your VPN is up you use the internal addresses.

Complicated/hacky answer: If all your clients are Linux based, you could possibly do something with policy routing and setup so the OpenVPN traffic still crosses the public network, and non OpenVPN traffic uses the tunnel. But It would almost certainly be extremely complicated to setup, and require some weird scripts. I haven't done it, and don't know of any tutorials.

Zoredache
  • 130,897
  • 41
  • 276
  • 420
  • But that breaks everything. I mean, The reason for this is to encapsulate packets that otherwise get their headers stripped along the route of public `eth2`. I need to send them through a tap so my server receives them clean, and I *need* to use `1.2.3.4` as the destination. – Jorge Fuentes González Oct 16 '19 at 19:58
  • What I don't understand is if I set the `--interface` for `eth1` and `eth2` it works, but when I set the source ip to `tap0` it won't get out there. I mean, what I need is to create a TCP packet, encapsulate it with OpenVPN and send that encapsulated packet through `tap0` no matter the contents of that packet. There must be a way for that as the packet has a source address. Maybe with routes or something like that. – Jorge Fuentes González Oct 16 '19 at 20:01
  • I already tell to OpenVPN to send the UDP packets it creates for `tap0` through `eth2`, as I'm binding to its IP, so source UDP packets have `eth2` IP. I don't understand why it can't create a UDP packet with the TCP packet I want and send it through `eth2`. – Jorge Fuentes González Oct 16 '19 at 20:04
  • I don't want all traffic go through OpenVPN actually. I want the packets created with source IP `tap0` one, go through `tap0`, nothing more. The packets are created specifically with `tap0` as the source (the same `curl --interface` do). This is my route table: https://i.imgur.com/cG0UQ4s.png (`11.11.11.0` is an internal IP) and this is the table when the packet comes from `tap0` IP: https://i.imgur.com/NYciWuE.png I think that I'm missing something, but also think that is possible (I'm a complete newbie with routing tables and such. Is my first time fiddling so hard with this kind of things). – Jorge Fuentes González Oct 16 '19 at 20:15
0

Got it! I think that is more a workaround than other thing, but it worked as expected.

Just had to create an iptables rule that will modify the destination of the packets if the source and destination corresponds to the public server IP and the tunnel IP:

iptables -t nat -A OUTPUT -s [client tap0 IP] -d [server public IP] -j DNAT --to-destination [server local IP]

And done! Works like a charm with MP-TCP.