0

I have an IPsec tunnel up and running (pure IPsec, without L2TP/GRE using strongswan 5.5.1) on Debian 9 VPS instance.

Currently it is IPv4 only so net.ipv4.ip_forward is set to 1 in sysctl.

Clients can successfully connect to remote instance over the internet using public IP of the server.

Remote peer address is set to A.B.C.1 with /etc/network and clients are getting addresses from subnet A.B.C.0/24 (starting from A.B.C.2) above which is set in ipsec.conf. I am able to ping server from client side using its IP in this subnet.

The thing is that internet traffic can't be routed using tunnel (checking done by sending ICMP to 8.8.8.8 through ipsec tunnel). I am very concerned about my iptables-fu but I really invested tons of time to figure out what's wrong and didn't succeed anyway.

Here's related rules from my filter iptables chain:

:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p esp -j ACCEPT
-A INPUT -p ah -j ACCEPT
-A INPUT -p udp -m udp --dport 500 -j ACCEPT
-A INPUT -p udp -m udp --dport 4500 -j ACCEPT
-A FORWARD -s A.B.C.0/24 -m policy --dir in --pol ipsec -j ACCEPT
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
COMMIT

And the nat chain:

:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -s A.B.C.0/24 -o <public interface> -m policy --dir out --pol ipsec -j ACCEPT
-A POSTROUTING -s A.B.C.0/24 -o <public interface> -j MASQUERADE
COMMIT

When I try to pass some requests tcpdump gives me this consecutive lines:

18:32:21.884250 IP my.local.ip > server.public.ip: ESP(spi=...,seq=...), length 104
18:32:21.884250 IP A.B.C.2 > 8.8.8.8: ICMP echo request, id 34822, seq 1024, length 30
18:32:21.884282 IP server.public.ip > 8.8.8.8: ICMP echo request, id 34822, seq 1024, length 30

Apparently either iptables drops request to 8.8.8.8 or its response gets dropped somewhere because can't be routed back to IPsec client.

How can I route traffic correctly or at least troubleshoot the origin of the issue?

Thanks.

gudvinr
  • 1
  • 1
  • You should see an inbound ICMP response from `8.8.8.8` to your server's IP (you won't see the natted response, though). Are you able to ping that IP from your server directly? – ecdsa Sep 09 '19 at 10:00
  • @ecdsa yes, I am able to ping `8.8.8.8` from the server directly (and there's a response packet in this case). This is quite obvious that inbound packets from `8.8.8.8` _should_ be seen but they aren't but this is indeed important thing to clarify. Which makes me think that the issue is not about iptables at all. – gudvinr Sep 09 '19 at 11:03
  • Have you been able to make any progress on this (e.g. compare the local and forwarded ICMP requests to see why one results in a response, while the other does not)? Did you try pinging other external hosts (preferably with access to at least one of them to capture traffic and compare inbound requests)? – ecdsa Sep 13 '19 at 09:53
  • @ecdsa sadly no. Only thing that I found out that to be able forward plain IPsec you need to have VTI (as mentioned in the answer) or ip xfrm support in Linux kernel but since on this particular instance I had openvz VM it seems there's no way to do that with kernel _that_ old. You need at least 3.15 for VTI and 4.19 for XFRM – gudvinr Sep 15 '19 at 12:52
  • You don't need a VTI or XFRM interfaces (that answer is just a rant, with a lot of misinformation). If you don't have IPsec support in the kernel (XFRM) neither would work anyway. While handling IPsec in the kernel provides a lot of advantages, it's not the only option (and OpenVZ can provide kernel-IPsec support, depends on the setup). You posted firewall rules with policy matching, since that only works with kernel-level IPsec, I wonder if you were able to install SAs/policies via _kernel-netlink_ plugin? Or did you use the _kernel-libipsec_ plugin? (The complete daemon logs might help.) – ecdsa Sep 16 '19 at 08:16
  • @ecdsa Debian only provides _kernel-netlink_ by default (as opposed to e.g. Ubuntu which has separate package) and you need to compile _kernel-libipsec_ plugin by youself. At the time of doing I didn't know about userspace implementation and most people over the internet complain about inability to use IPsec in ovz containers. I should ask my provider but I had no errors in setup process so either it works but fails on client side or silently broken somewhere in the host kernel. – gudvinr Sep 16 '19 at 11:38
  • If the IPsec SAs and policies were installed without errors via _kernel-netlink_, that means there is kernel-level IPsec support. So that's good. But again, if you NAT the inbound messages so they basically look like messages originating from the server itself, there is really no reason why there shouldn't be a response (or why the message wouldn't be forwarded in the first place). However, it's definitely possible that there is a strange routing problem or some other issue in this OpenVZ setup. – ecdsa Sep 16 '19 at 15:25

1 Answers1

0

Of course it can not. According to your initial information, you are using the policy-based IPSec mode, which is also called legacy IPSec. In this case only the traffic matching the security policies - SP - is forwarded to the remote security gateway. What is more sad and more important - it's not routed, it's surgically removed from the usual packet flow of your OS and forwarded via the tunnel. So in this case you need to describe all of the traffic that you want to go through the tunnel in your policies - and - spoiler alert - usually this is technically impossible.

So that's the reason why this setup is called legacy - in most cases you want the IPSec routed mode, so you are either using the VTI mode on your stack, or you are using the intermediate routing interface with intermediate incapsulation, like GRE, - so in your policies you only describe matching traffic as GRE-traffic between local and remote end of tunnel (on both sides) and the you merely use routing.

VTI, on the other hand, doesn't use the intermediate encapsulation, and is purely an IPSec interface.

Both approaches are supported by the strongswan.

Unfortunately, the procedure of setting up these methods is out of the scope of this answer, however I gave enough patterns for googling it (seems to be an easy task).

drookie
  • 8,625
  • 1
  • 19
  • 29