OpenVPN client connected to a server while listening to SSH?

Hi all,

I want to have a Linode with:

  • SSH server listening to the Linode's public IP port 22

  • OpenVPN (client!) connected to an external OpenVPN server

  • Tunnel all the traffic that the Linode generates through the OpenVPN.

I have created a fresh new Linode (with Ubuntu) to do my tests. I thought it was a fairly easy setup, but I am running into issues.

Basically, as soon as I start the OpenVPN, any SSH connection drops, and I cannot connect again to the Linode at all using its public IP.

I am far from being an expert with iptables, and I cannot find the magic lines that will let me connect via SSH to my Linode while the OpenVPN tunnel is on.

Can anyone tell me how to get this configuration working? Or maybe point me to a website where it is explained? I have googled it and all I can find is people asking the same question - but no answers…

Thanks a lot in advance,

Fernando

16 Replies

You'll need to add a route back to your local IP address via the normal ethernet interface (i.e. not the tunnel). 'ip route add 2001:db8:beef::1234 via fe80::1 dev eth0' should do it, substituting your real IP address and your default gateway's IP address.

This will mean all traffic to your local IP address will bypass the VPN. Them's the breaks.

Thank you for your answer, but I didn't manage to get it work.

"ip route add via dev eth0" just says "RTNETLINK answers: No such process".

I have no idea how to continue from here…

Hi,

(First, I assume you've tested the VPN and verified that it's actually working, i.e. you can make connections from your Linode and they're routed over the VPN.)

This is a classic problem: when you connect to the Linode by its public IP address, the return packets get routed over the VPN. You need to force these packets to be routed over the public eth interface. These route commands should do the trick:

ip rule add from x.x.x.x table 128
ip route add table 128 to y.y.y.y/y dev ethX
ip route add table 128 default via z.z.z.z

Where x.x.x.x is your Linode's public IP, y.y.y.y/y should be the subnet of your Linode's public IP address, ethX should be your Linode's public Ethernet interface, and z.z.z.z should be the default gateway.

For example:

ip rule add from 172.16.9.132 table 128
ip route add table 128 to 172.16.9.0/24 dev eth0
ip route add table 128 default via 172.16.9.1

Note that this will apply to all ports, not just ssh. If you only want to accept ssh traffic on your public IP address you'll need iptables rules like these:

iptables -A INPUT -d x.x.x.x -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -d x.x.x.x -j DROP

(again, x.x.x.x is your public IP address)

Thank you, thank you, thank you!

I have created two little bash files for /etc/network/if-up.d and if-down.d to run those 3 lines automatically using the real values of the network.

And as far as I can tell, everything is working correctly! OpenVPN up and running, traffic going through the VPN, and SSH still listening (and replying) through eth0.

For the record, I had ufw with a single allow rule for the SSH port - that seems to work now even after these changes.

Thank you again AGWA! Very much appreciated.

Regards, Fernando

@AGWA:

Hi,

(First, I assume you've tested the VPN and verified that it's actually working, i.e. you can make connections from your Linode and they're routed over the VPN.)

This is a classic problem: when you connect to the Linode by its public IP address, the return packets get routed over the VPN. You need to force these packets to be routed over the public eth interface. These route commands should do the trick:

ip rule add from x.x.x.x table 128
ip route add table 128 to y.y.y.y/y dev ethX
ip route add table 128 default via z.z.z.z

Where x.x.x.x is your Linode's public IP, y.y.y.y/y should be the subnet of your Linode's public IP address, ethX should be your Linode's public Ethernet interface, and z.z.z.z should be the default gateway.

For example:

ip rule add from 172.16.9.132 table 128
ip route add table 128 to 172.16.9.0/24 dev eth0
ip route add table 128 default via 172.16.9.1

Note that this will apply to all ports, not just ssh. If you only want to accept ssh traffic on your public IP address you'll need iptables rules like these:

iptables -A INPUT -d x.x.x.x -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -d x.x.x.x -j DROP

(again, x.x.x.x is your public IP address)

Does this work over IPSEC? Thank you AGWA, looking forward to making my own bash file :)

I have this exact problem. No ssh or just about anything else when the VPN is connected. This is a pain because the lack of connectivity makes the VPN hard to turn off so I'm effectively locked out when trying to connect remotely if I forget to turn of the VPN. Even killing the VPN server doesn't remove the default routes on the client.

My issue is that my distro / kernel doesn't support "ip rule".

I would like to achieve the same thing using iptables instead.

Alternatively, if I could somehow route traffic from certain IPs via tun0, then I wouldn't need to push "redirect-gateway def1 bypass-dhcp" which causes the problem.

I have wasted hours of my life on this problem. Any ideas? Thanks.

> My issue is that my distro / kernel doesn't support "ip rule".

Is it that the "ip" command doesn't exist, or does it exist but your kernel doesn't support it? If it's the former, look for a package called "iproute" or "iproute2." If it's the latter, are you using a stock kernel or did you compile your own? If you compiled your own, compile a new one with "IP: Advanced Router" support (CONFIGIPADVANCED_ROUTER). I'd be very surprised if a distro shipped a kernel without this enabled, or didn't have an iproute package available - this is pretty mainstream stuff.

I'm pretty sure it's not possible to accomplish this with iptables. You need to cause certain packets to use a different default gateway, which iptables can't do on its own.

I'm not sure what you mean by "route traffic from certain IPs via tun0." If you mean you only want to route packets to certain IPs via the VPN, you can push specific routes to the VPN client (push "route 1.2.3.4" push "route 5.6.7.8" etc.) instead of pushing redirect-gateway.

Firstly, thanks very much for the reply.

Yes the 'ip' command does exist but alas it doesn't support the 'rule' option. I'm actually running on a Synology NAS box backed with BusyBox. I don't much fancy compiling a kernel for this thing either.

nas> ip
BusyBox v1.16.1 (2012-12-11 12:54:00 CST) multi-call binary.

Usage: ip [OPTIONS] {address | route | link | } {COMMAND}

> I'm not sure what you mean by "route traffic from certain IPs via tun0."

I have a Google TV which I want to access the web via the VPN. Nothing else on my lan needs to. If it routes all of its traffic over the gateway, then I can use the TV as intended but it renders the NAS box inaccessible from anywhere outside the LAN. I now understand that I can push routes from the VPN server to the VPN client but that's not what I want :(.

I'm not sure if the kernel supports this or how to check. I did update BusyBox and the new version does show a rule command but sadly:

nas> ./busybox-1.20.2 ip rule
ip: RTNETLINK answers: Operation not supported
ip: dump terminated

I guess that means new kernel time.

Thanks again.

You're welcome!

> I have a Google TV which I want to access the web via the VPN. Nothing else on my lan needs to. If it routes all of its traffic over the gateway, then I can use the TV as intended but it renders the NAS box inaccessible from anywhere outside the LAN. I now understand that I can push routes from the VPN server to the VPN client but that's not what I want :(.

I understand now. It's possible, but it too requires advanced router support, so it looks like you're stuck building a new kernel.

The rules would be something like this (warning: not tested):

ip rule add from x.x.x.x table 128
ip route add table 128 default via y.y.y.y

where x.x.x.x is your Google TV and y.y.y.y is the remote end of the VPN. If you do this, you wouldn't need to push redirect-gateway to the client.

Edit: I should mention that the "ip route" command can only be run when the VPN is up, and will go away if the VPN dies. You might want to put the "ip rule" command in a system startup script, and run the "ip route" command from an OpenVPN "up" script.

Screw it… gonna buy a cheap router, sitck DDWRT on it and make that OpenVPN client instead :-) Much less hassle.

Thanks again.

@AGWA:

Hi,

(First, I assume you've tested the VPN and verified that it's actually working, i.e. you can make connections from your Linode and they're routed over the VPN.)

This is a classic problem: when you connect to the Linode by its public IP address, the return packets get routed over the VPN. You need to force these packets to be routed over the public eth interface. These route commands should do the trick:

ip rule add from x.x.x.x table 128
ip route add table 128 to y.y.y.y/y dev ethX
ip route add table 128 default via z.z.z.z

Where x.x.x.x is your Linode's public IP, y.y.y.y/y should be the subnet of your Linode's public IP address, ethX should be your Linode's public Ethernet interface, and z.z.z.z should be the default gateway.

For example:

ip rule add from 172.16.9.132 table 128
ip route add table 128 to 172.16.9.0/24 dev eth0
ip route add table 128 default via 172.16.9.1

Note that this will apply to all ports, not just ssh. If you only want to accept ssh traffic on your public IP address you'll need iptables rules like these:

iptables -A INPUT -d x.x.x.x -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -d x.x.x.x -j DROP

(again, x.x.x.x is your public IP address)

Seriously, thank you, this is with your advice I finally complete a huge project :)!

Regards.

Hey! Sorry that I have to bring this thread up again but I have a similar issue. I have a Raspberry Pi3 with OSMC running on it. I managed to be able to access it via ssh from anywhere (Dyndns in my router and opened port 22). However, I cannot access it anymore if connected to a VPN-Server via OpenVpn. I tried to do what AGWA recommended in this thread but it doesn't work. To be honest I am a little bit struggling with the different numbers. So x.x.x.x is my Pi3's public address which is also my router's public IP, right? The one which changes everyday? How do I find out the subnet of my Pi's public IP address and the default gateway? What happens when I get a new IP from my Provider?

Thanks in advance

This is the IPv6 equivalent:

ip -6 rule add from 2a01:7e00::x:x:x:x table 129
ip -6 route add table 129 to 2a01:7e00::/64 dev eth0
ip -6 route add table 129 default via fe80::1 dev eth0

Sorry to resurrect this post but it may help someone else like myself in the future. I have completed the above steps using my IP/gateway info and I can successfully connect my VPN and keep SSH connections alive, but my DNS seems to no longer be working when connected to the VPN.

I ran these steps (substituting my IP/Gateway/Subnet):

ip rule add from x.x.x.x table 128
ip route add table 128 to y.y.y.y/y dev ethX
ip route add table 128 default via z.z.z.z

And connected my OpenVPN connection while remaining connected via SSH.

I can then ping remote servers via their IP address, but not their domain name

and I can ping a remote server via IP:

PING 172.217.15.78 (172.217.15.78) 56(84) bytes of data.
64 bytes from 172.217.15.78: icmpseq=1 ttl=53 time=89.0 ms 64 bytes from 172.217.15.78: icmpseq=2 ttl=53 time=87.10 ms
64 bytes from 172.217.15.78: icmp_seq=3 ttl=53 time=88.6 ms

but not via domain name:

ping: google.com: Temporary failure in name resolution

Is there an additional step I need to take to ensure DNS works with my VPN activated? I use this same VPN service on my local desktop with no issues.

Thanks!

@tokenwizard I'm having the exact same issue, have you found a solution?
I'm about to start investigating what's wrong with the DNS after I connect my remote server to a VPN via OpenVPN, but it would be nice to have a heads up :)
Anyone can help with this?

DNS uses UDP port 53. You have to make sure that this traffic is not blocked by any of your security measures.

I'll bet if you take a close look, you're blocking DNS traffic somewhere/somehow…

-- sw

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct