IPIP IPsec VPN tunnel between a Linux machine and Mikrotik through the provider's NAT

Linux: Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)

  • Eth0 1.1.1.1/32 external IP
  • ipip-ipsec0 192.168.0.1/30 will be our tunnel

MikroTik: CCR 1009, RouterOS 6.46.5

  • Eth0 10.0.0.2/30 internal IP from the provider. The external IP of the provider's NAT is dynamic.
  • ipip-ipsec0 192.168.0.2/30 will be our tunnel

We will set up the IPsec tunnel on the Linux machine using racoon. I won't go into the details, there's good article at vvpoloskin.

We install the necessary packages:

sudo install racoon ipsec-tools

We configure racoon, which will act as the IPsec server. Since Mikrotik in main mode cannot pass an additional client identifier, and the external IP address it connects to Linux is dynamic, using a preshared key (password authentication) is not possible, as the password must match either the IP address of the connecting host or the identifier.

We will use RSA key authentication.

The racoon daemon uses keys in RSA format, while Mikrotik uses PEM format. If you generate keys with the plainrsa-gen utility that comes with racoon, you will not be able to convert the public key for Mikrotik into PEM format with it — it only converts one way: PEM to RSA. The key generated by plainrsa-gen could not be read by either openssl or ssh-keygen, so it cannot be converted with their help either.

We will generate a PEM key using openssl, and then convert it for racoon using plainrsa-gen:

#  Генерируем ключ
openssl genrsa -out server-name.pem 1024
# Извлекаем публичный ключ
openssl rsa -in server-name.pem -pubout > server-name.pub.pem
# Конвертируем
plainrsa-gen -i server-name.pem -f server-name.privet.key
plainrsa-gen -i server-name.pub.pem -f server-name.pub.key

We will place the obtained keys in the folder: /etc/racoon/certs/server. Don't forget to set the owner to the user under which the racoon daemon runs (usually root) and set the permissions to 600.

I will describe Mikrotik configuration when connecting through WinBox.

Upload the key server-name.pub.pem to Mikrotik: Menu 'Files' — 'Upload'.

Open the 'IP' — 'IP sec' section — 'Keys' tab. Now we generate the keys — click 'Generate Key', then export the Mikrotik public key 'Export Pub. Key', you can download it from the 'Files' section by right-clicking on the file — 'Download'.

Import the public key from racoon using 'Import', in the dropdown list of the 'File name' field find the previously uploaded server-name.pub.pem.

The Mikrotik public key needs to be converted

plainrsa-gen -i mikrotik.pub.pem -f mikrotik.pub.key

and placed in the folder /etc/racoon/certs without forgetting about the owner and permissions.

Racoon config with comments: /etc/racoon/racoon.conf

log info; # Logging level, use Debug or Debug2 for troubleshooting.

listen {

    isakmp 1.1.1.1 [500]; # Address and port on which the daemon will listen.
    isakmp_natt 1.1.1.1 [4500]; # Address and port for the daemon to listen to clients behind NAT.
    strict_address; # Perform mandatory binding checks against the specified IPs.
}

path certificate "/etc/racoon/certs"; # Path to the folder containing certificates.

remote anonymous { # Section defining parameters for daemon operation with ISAKMP and mode negotiation with connecting hosts. Since the IP from which Mikrotik connects is dynamic, we use anonymous, allowing connections from any address. If the hosts have a static IP, a specific address and port can be specified.

    passive on; # Sets the "server" mode of operation for the daemon; it will not attempt to initiate connections.
    nat_traversal on; # Enables NAT-T mode for clients if they are behind NAT.
    exchange_mode main; # Connection parameters exchange mode, in this case, negotiation.
    my_identifier address 1.1.1.1; # Identify our Linux host by its IP address.
    certificate_type plain_rsa "server/server-name.priv.key"; # Server's private key.
    peers_certfile plain_rsa "mikrotik.pub.key"; # Mikrotik's public key.

    proposal_check claim; # ISAKMP tunnel parameter negotiation mode. Racoon will use the connecting host's (initiator's) session lifetime and key length if the session lifetime is greater or the key length shorter than the initiator's. If the session lifetime is shorter than the initiator's, racoon will use its own session lifetime and send a RESPONDER-LIFETIME message.
    proposal { # ISAKMP tunnel parameters.

        encryption_algorithm aes; # Encryption method for the ISAKMP tunnel.
        hash_algorithm sha512; # Hashing algorithm used for the ISAKMP tunnel.
        authentication_method rsasig; # Authentication method for the ISAKMP tunnel - using RSA keys.
        dh_group modp2048; # Key length for the Diffie-Hellman algorithm in ISAKMP tunnel negotiation.
        lifetime time 86400 sec; # Session lifetime.
    }

    generate_policy on; # Automatic ESP tunnel creation from the request received from the connecting host.
}

sainfo anonymous { # Parameters for ESP tunnels, anonymous - specified parameters will be used as defaults. Different parameters can be set for different clients, ports, protocols, with matching based on IP addresses, ports, protocols.

    pfs_group modp2048; # Key length for the Diffie-Hellman algorithm for ESP tunnels.
    lifetime time 28800 sec; # Lifetime of ESP tunnels.
    encryption_algorithm aes; # Encryption method for ESP tunnels.
    authentication_algorithm hmac_sha512; # Hash algorithm used for ESP tunnel authentication.
    compression_algorithm deflate; # Compress transmitted data; only one compression algorithm is offered.
}

Mikrotik Configuration

Return to the "IP" — "IPsec" section

The "Profiles" tab
Parameter
Value

Name
At your discretion (default is default)

Hash Algorithm
sha512

Encryption Algorithm
aes-128

DH Group
modp2048

Proposhal_check
claim

Lifetime
1d 00:00:00

NAT Traversal
true (check the box)

DPD
120

DPD Maximum failure
5

The "Peers" tab
Parameter
Value

Name
At your discretion (further MyPeer)

Address
1.1.1.1 (IP of the Linux machine)

Local Address
10.0.0.2 (IP of the WAN interface of Mikrotik)

Profile
default

Exchange Mode
main

Passive
false

Send INITIAL_CONTACT
true

The "Proposal" tab
Parameter
Value

Name
At your discretion (further MyPeerProposal)

Auth. Algorithms
sha512

Encr. Algorithms
aes-128-cbc

Lifetime
08:00:00

PFS Group
modp2048

The "Identities" tab
Parameter
Value

Peer
MyPeer

Auth. Method
rsa key

Key
mikrotik.privet.key

Remote Key
server-name.pub.pem

Policy Template Group
default

Notrack Chain
empty

My ID Type
auto

Remote ID Type
auto

Match By
remote id

Mode Configuration
empty

Generate Policy
no

The "Policies — General" tab
Parameter
Value

Peer
MyPeer

Tunnel
true

Src. Address
192.168.0.0/30

Dest. Address
192.168.0.0/30

Protocol
255 (all)

Template
false

The "Policies — Action" tab
Parameter
Value

Action
encrypt

Level
require

IPsec Protocols
esp

Proposal
MyPeerProposal

Most likely, like me, you have configured snat/masquerade on your WAN interface, this rule needs to be adjusted so that outgoing IPsec packets go through our tunnel:
Go to the "IP" — "Firewall" section.
The "NAT" tab, open our snat/masquerade rule.

The "Advanced" tab
Parameter
Value

IPsec Policy
out: none

Restart the racoon daemon

sudo systemctl restart racoon

If racoon does not start on restart, there is an error in the config; in syslog, racoon outputs information about the line number where the error was found.

The racoon daemon starts before the network interfaces are up; and we specified the strict_address option in the listen section; thus, it is necessary to add this to the systemd unit file for racoon.
/lib/systemd/system/racoon.service, в секцию [Unit], строку After=network.target.

Now our IPsec tunnels should be up, check the output:

sudo ip xfrm policy

src 192.168.255.0/30 dst 192.168.255.0/30 
    dir out priority 2147483648 
    tmpl src 1.1.1.1 dst "NAT IP through which Mikrotik connects"
        proto esp reqid 0 mode tunnel
src 192.168.255.0/30 dst 192.168.255.0/30 
    dir fwd priority 2147483648 
    tmpl src "NAT IP through which Mikrotik connects" dst 1.1.1.1
        proto esp reqid 0 mode tunnel
src 192.168.255.0/30 dst 192.168.255.0/30 
    dir in priority 2147483648 
    tmpl src "NAT IP through which Mikrotik connects" dst 1.1.1.1
        proto esp reqid 0 mode tunnel

If the tunnels did not come up, check the syslog or journalctl -u racoon.

You now need to configure L3 interfaces so that traffic can be routed. There are different options; we will use IPIP since it's supported by Mikrotik. I would have preferred VTI, but unfortunately, it has not been implemented in Mikrotik yet. IPIP differs from it in that it can additionally encapsulate multicast and tag packets (fwmark) which can be filtered in iptables and iproute2 (policy-based routing). If maximum functionality is needed — for instance, GRE. But keep in mind that we pay a high overhead for additional functionality.

You can check a decent overview of tunnel interfaces here.

On Linux:

# Создаем интерфейс
sudo ip tunnel add ipip-ipsec0 local 192.168.255.1 remote 192.168.255.2 mode ipip
# Активируем
sudo ip link set ipip-ipsec0 up
# Назначаем адрес
sudo ip addr add 192.168.255.1/30 dev ipip-ipsec0

Now you can add routes for networks behind Mikrotik

sudo ip route add A.B.C.D/Prefix via 192.168.255.2

To ensure our interface and routes are up after a reboot, the interface must be described in /etc/network/interfaces and include route additions in the post-up, or you can write everything in one file, for example, /etc/ipip-ipsec0.conf, and trigger it through post-up. Don't forget about file ownership, permissions, and making it executable.

Below is an example of the file

#!/bin/bash
ip tunnel add ipip-ipsec0 local 192.168.255.1 remote 192.168.255.2 mode ipip
ip link set ipip-ipsec0 up
ip addr add 192.168.255.1/30 dev ipip-ipsec0

ip route add A.B.C.D/Prefix via 192.168.255.2

On Mikrotik:

In the 'Interfaces' section, add a new 'IP tunnel' interface:

In the 'IP tunnel' tab — 'General'
Parameter
Value

Name
At your discretion (here, IPIP-IPsec0)

MTU
1480 (if not specified, Mikrotik starts reducing MTU to 68)

Local Address
192.168.0.2

Remote Address
192.168.0.1

Ipsec Secret
Deactivate the field (otherwise a new Peer will be created)

Keepalive
Deactivate the field (otherwise the interface will constantly turn off, as Mikrotik has a specific format for these packets that does not work with Linux)

DSCP
inherit

Dont Fragment
no

Clamp TCP MSS
true

Allow Fast Path
true

In the 'IP' section — 'Addresses', add the address:

Parameter
Value

Address
192.168.0.2/30

Interface
IPIP-IPsec0

Now you can add routes to networks behind the Linux machine. When adding a route, the gateway will be our IPIP-IPsec0 interface.

PS

Since our Linux server serves as a transit point, it makes sense to set the Clamp TCP MSS parameter for IPIP interfaces:

create a file /etc/iptables.conf with the following content:

*mangle
-A POSTROUTING -o ipip+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
COMMIT

and in /etc/network/interfaces
post-up iptables-restore < /etc/iptables.conf

In the network behind Mikrotik, I have nginx (IP 10.10.10.1) running, let's make it accessible from the internet by adding to /etc/iptables.conf:

*nat
-A PREROUTING -d 1.1.1.1/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 10.10.10.1
#On Mikrotik, in the mangle table, you need to add a route rule with the destination 192.168.0.1 for packets with a source address of 10.10.10.1 on ports 80, 443.

# Also, on Linux, OpenVPN server 172.16.0.1/24 runs; for clients connecting to it as a gateway, we provide internet access
-A POSTROUTING -s 172.16.0.0/24 -o eth0 -j SNAT --to-source 1.1.1.1
COMMIT 

Don’t forget to add the appropriate permissions in iptables if you have packet filtering enabled.

Stay healthy!

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster