IPsec site-to-site tunnel

Hi, I'm using the new 18.06.0 and trying to get an IPsec site-to-site tunnel set up with an EdgeRouter Lite, but I seem to be having trouble getting the child SAs established.

The log on the OpenWRT side says:

Tue Jul 31 15:56:38 2018 authpriv.info ipsec: 08[IKE] initiating IKE_SA other-other_lan[3] to w.x.y.z
Tue Jul 31 15:56:38 2018 daemon.info ipsec: 08[IKE] initiating IKE_SA other-other_lan[3] to w.x.y.z
Tue Jul 31 15:56:40 2018 authpriv.info ipsec: 16[IKE] establishing CHILD_SA other-other_lan{4} reqid 1
Tue Jul 31 15:56:40 2018 daemon.info ipsec: 16[IKE] establishing CHILD_SA other-other_lan{4} reqid 1

And the log on the ER-Lite side says:

Jul 31 15:56:38 16[IKE] <3> a.b.c.d is initiating an IKE_SA

Not many details on what went wrong on either end, unfortunately :frowning: But I think the ER-Lite is rejecting the phase 2 proposal.

/etc/config/ipsec on OpenWRT (BTW, I think https://openwrt.org/docs/guide-user/services/vpn/ipsec/strongswan/basic is out of date; some of the config option names don't seem to be used by /etc/init.d/ipsec, such as pfs_group and authentication_algorithm):

config 'ipsec'
list listen ''
option 'debug' '2'

config 'remote' 'other'
option 'enabled' '1'
option 'gateway' 'w.x.y.z'
option 'authentication_method' 'psk'
option 'pre_shared_key' 'my PSK'
option 'exchange_mode' 'aggressive'
option 'local_identifier' 'me'
list 'crypto_proposal' 'pre_g14_aes_sha1'
list 'tunnel' 'other_lan'

config 'crypto_proposal' 'pre_g14_aes_sha1'
option 'encryption_algorithm' 'aes128'
option 'hash_algorithm' 'sha1'
option 'dh_group' 'modp2048'

config 'tunnel' 'other_lan'
option 'local_subnet' '10.1.1.0/24'
option 'remote_subnet' '10.2.1.0/24'
option 'crypto_proposal' 'g14_aes_sha1'

config 'crypto_proposal' 'g14_aes_sha1'
option 'dh_group' 'modp2048'
option 'encryption_algorithm' 'aes128'
option 'hash_algorithm' 'sha1'

Which generated this /var/ipsec/ipsec.conf:

conn other-other_lan
left=%any
right=w.x.y.z
leftsubnet=10.1.1.0/24
ikelifetime=3h
lifetime=1h
margintime=9m
keyingtries=3
dpdaction=none
dpddelay=30s
leftauth=psk
rightauth=psk
rightsubnet=10.2.1.0/24
auto=route
leftid=me
keyexchange=ikev2
esp=aes128-sha1-modp2048
ike=aes128-sha1-modp2048
type=tunnel

/etc/ipsec.conf on the ER-Lite:

conn peer-a.b.c.d-tunnel-1
left=w.x.y.z
right=a.b.c.d
leftsubnet=10.2.1.0/24
rightsubnet=10.1.1.0/24
ike=aes128-sha1-modp2048!
keyexchange=ikev2
reauth=no
ikelifetime=28800s
esp=aes128-sha1-modp2048!
keylife=3600s
rekeymargin=540s
type=tunnel
compress=no
authby=secret
auto=route
keyingtries=%forever

The esp entry in both ipsec.conf files match, so it seems like the phase 2 proposal should be OK.

Any ideas? Or things I can do to enable more debug logging? I tried setting option 'debug' '2' already, but that didn't seem to change anything. (Despite the doc page saying "Logs are written to /var/log/charon.log", there's no file with that name).

tcpdump feeding wireshark on another machine for debugging

I tried that already, but it's encrypted, as one would expect... OpenWRT sends IKE_SA_INIT, ER-Lite responds. OpenWRT sends IKE_AUTH, ER-Lite responds:

Internet Security Association and Key Management Protocol
Initiator SPI: 044f0d4b9d351c62
Responder SPI: 3c89f3cbb64a5453
Next payload: Encrypted and Authenticated (46)
Version: 2.0
Exchange type: IKE_AUTH (35)
Flags: 0x20 (Responder, No higher version, Response)
Message ID: 0x00000001
Length: 76
Payload: Encrypted and Authenticated (46)
Next payload: Notify (41)
0... .... = Critical Bit: Not Critical
.000 0000 = Reserved: 0x00
Payload length: 48
Initialization Vector: a870eb97
Encrypted Data

But I did find that sending SIGHUP to charon got it to honor the debug logging that I had set. I thought /etc/init.d/ipsec restart would stop and restart charon, but I guess not?

So it turns out what the other end is trying to say is:

Tue Jul 31 16:42:52 2018 daemon.info ipsec: 12[IKE] received AUTHENTICATION_FAILED notify error

I guess it has to do with the option 'local_identifier'/leftid setting? On the ER-Lite, /etc/ipsec.secrets has:

w.x.y.z a.b.c.d : PSK "my PSK"

(w.x.y.z is the ER-Lite's IP and a.b.c.d is OpenWRT's). So I thought maybe leftid needed to be OpenWRT's IP address, so I changed the line in OpenWRT's /etc/config/ipsec to:

option 'local_identifier' 'a.b.c.d'

Didn't help any though; same AUTHENTICATION_FAILED :frowning:

Your device isn't using NAT (behind another router/firewall)...is it?

No NAT on either end.

Made some progress though; changed option 'exchange_mode' from 'aggressive' to 'main' (OpenWRT is on a dynamic IP, but in practice it doesn't change), and I think the tunnel is now established. However, it seems that there's problems with getting traffic to go over the tunnel:

If I ping 10.2.1.x from the 10.1.1.x side (i.e., ping from the OpenWRT side to the ER-Lite side), there's no traffic on the tunnel. If I ping 10.1.1.x from the 10.2.1.x side, I see ESP packets come in:

17:13:49.619794 IP w.x.y.z > a.b.c.d: ESP(spi=0xc058e5d8,seq=0x19), length 132

But OpenWRT isn't sending the decrypted ping packet out the LAN interface.

Perhaps a firewall issue? https://openwrt.org/docs/guide-user/services/vpn/ipsec/strongswan/site2site mentions adding firewall rules to allow traffic from the LAN to the remote subnets, but I don't have any rules that block outgoing traffic. I don't currently have any rules besides the default ones.

Please show us from your firewall configuration:

  • defaults
  • zone wan
  • zone vpn, if it exists (you created it)
  • forwardings, if related to these zones

Do you want to allow non-VPN internet access for clients from the OpenWrt router's LAN?

I didn't create a vpn zone. I do want clients on the OpenWrt's LAN to get to the internet. So LAN to 10.2.1.0/24 goes over the IPsec tunnel, LAN to 10.1.1.0/24 stays on the LAN, and LAN to everywhere else goes to the internet.

Here's my /etc/config/firewall (there's nothing in /etc/firewall.user but comments):

config defaults
        option syn_flood '1'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'

config zone
        option name 'lan'
        list network 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'

config zone
        option name 'wan'
        list network 'wan'
        list network 'wan6'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option src_ip 'fc00::/6'
        option dest_ip 'fc00::/6'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config include
        option path '/etc/firewall.user'

The wan interface is set up with masquerading (source NAT) by default. This affects both plaintext traffic to the internet and VPN traffic towards the remote LAN. When IPsec decides whether to pass through or to tunnel a packet, it compares the packet's source IP, destination IP, and optionally other header fields with its own configured policy. Masquerading changes the source IP, which causes a mismatch in this comparison, and the packet is not sent through the VPN.

You have to make sure the masquerading is not applied to VPN traffic. There may be more than one solution, here is my setup.

  • add to all non-VPN zones (wan and lan in your case):
    option extra_src   '-m policy --dir in --pol none'
    option extra_dest  '-m policy --dir out --pol none'
    
    
  • create a vpn zone:
    config zone
      option name        vpn
      option input       ACCEPT
      option output      ACCEPT
      option forward     ACCEPT
      option subnet      10.2.1.0/24
      option extra_src   '-m policy --dir in --pol ipsec --proto esp'
      option extra_dest  '-m policy --dir out --pol ipsec --proto esp'
      option mtu_fix     1
    

Adjust input/output/forward policy, and add forwardings or custom rules as needed.

These pass-through rules have no effect here, they are used when a machine in your LAN wants to act as a VPN gateway and receive VPN connection requests.
However, you should allow VPN traffic for the OpenWrt gateway itself:

config rule
  option name       Allow-IKE-input
  option src        wan
  option proto      udp
  option dest_port  '500 4500'
  option target     ACCEPT

config rule
  option name       Allow-ESP-input
  option src        wan
  option proto      esp
  option target     ACCEPT

These rules handle IKE and encrypted traffic, while the vpn zone above handles the traffic before encryption and after decryption. Both are necessary.

4 Likes

That worked; thanks!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.