I have a server that routes all of its traffic through wireguard. When I start the wireguard, all ports listening on this server's public IP are unavailable – even ssh does not work.
What I want is to allow incoming traffic on a port (ssh for example) from any IP, but use wireguard for any outgoing connection.
Example:
MY_SERVER to any public ip -> use wireguard peer for routing (other servers should see wireguard peer's IP as source). This is working by having AllowedIPs = 0.0.0.0/0
in wireguard conf.
Any public IP to MY_SERVER -> this is not working when wireguard is enabled. If I stop wireguard it works.
Any ideas how can I allow incoming connections on my public IP and route outgoing connections through wireguard?
Update:
The main issue is that I am getting asymmetric routing due to wireguard routing all packets through it. So when incoming connection on public IP for given port comes in, it's reply is routed over wg0 instead of public interface and never makes it back to client.
I was able to somewhat fix it by adding ip rule add sport PORT table main
but not sure if there is a better fix so I don't have to 1 by 1 add all ports – I want any port I start listening on to be routed correctly. Also, this fix works for TCP but not for UDP. Would be great if I can have it working for both protocols.
Best Answer
Your routing tables are stateless, they don't have any information about a packet being an answer or your port being bound. So you can use the connection table to add a mark when a connection is made to the server interface (not the wireguard one), and then restoring this mark for every packet of this connection.
You can then use this mark in a routing rule:
Or if you use nftables:
Or you can do it with listing ports in rules, it might be the cleaner. For UDP, you want services to listen on a single IP address (not 0.0.0.0), and then the
ip rule
should work.