FreeBSD suggests using Racoon as the IKE daemon, and I buy that recommendation since RouterOS also uses racoon internally (hint: look at the ipsec,debug)

But this "simple"-tunnel method of RouterOS it a bit tricky to replicate on a default racoon setup. In this example I will use a IP-in-IP tunnel (also called ipencap) and has IP Protocol 4 (IP/4), but using a GRE (IP/47) should also be fine.

  • Route-based tunnel - not Proxy/Policy-based
  • Using IP-in-IP tunnel type ("ipencap" / IP Protocol 4)
  • Site A tunnel endpoint - 192.168.254.1/32
  • Site A local network - 192.168.1.0/24
  • Site B tunnel endpoint - 192.168.254.2/32
  • Site B local network - 192.168.2.0/24

SITE_A_IP and SITE_B_IP is the corresponding public IP-addresses. This howto doesn't cover any required firewall openings.

This is what I found out and works.

Site A - RouterOS

1. Setup tunnel interface on RouterOS, and setup a linknet

/interface ipip
add name=tun1 ipsec-secret=XXXXXXXXXX local-address=SITE_A_IP remote-address=SITE_B_IP
/ip address
add address=192.168.254.1/30 interface=tun1
/ip route
add dst-address=192.168.2.0/24 gateway=192.168.254.2

You're done on RouterOS.

Site B - FreeBSD

1. Setup tunnel interface and services on your FreeBSD (or similar system)

/etc/rc.conf:

cloned_interfaces="gif0"
ifconfig_gif0="inet 192.168.254.2 192.168.254.1 netmask 255.255.255.255 tunnel SITE_B_IP SITE_A_IP"
racoon_enable="YES"
ipsec_enable="YES"
ipsec_file="/usr/local/etc/racoon/setkey.conf"

gateway_enable="YES"
static_routes="net1"
route_net1="-net 192.168.1.0/24 192.168.250.1"

2. Configuration for racoon. Please note the "address SITE_B_IP 4 address SITE_A_IP 4" where the 4 is for ipencap (IP/4) tunnel packets.

/usr/local/etc/racoon/racoon.conf:

path pre_shared_key "/usr/local/etc/racoon/psk.txt";
log notify;

listen {
    isakmp          SITE_B_IP [500];
}

remote SITE_A_IP [500] {
    exchange_mode       main;
    proposal_check      obey;

    # phase 1
    proposal {
        encryption_algorithm    aes 128;
        hash_algorithm          sha1;
        authentication_method   pre_shared_key;
        lifetime time           3600 secs;
        dh_group                2;
    }
}

# phase 2
sainfo (address SITE_B_IP 4 address SITE_A_IP 4) {
    pfs_group                       2;
    lifetime                        time 3600 sec;
    encryption_algorithm            aes 128;
    authentication_algorithm        hmac_sha256, hmac_sha1;
    compression_algorithm           deflate;
}

3. This one is tricky, the IPsec kernel policy configuration. This tells the kernel IP-stack - that traffic from SITE_B_IP to (out) SITE_A_IP that is of type ipencap (IP/4) shall be of encrypted with IPsec transport type ESP. The next line is for the opposite direction.

/usr/local/etc/racoon/setkey.conf:

flush;
spdflush;
spdadd SITE_B_IP SITE_A_IP ipencap -P out ipsec esp/transport/SITE_B_IP-SITE_A_IP/require;
spdadd SITE_A_IP SITE_B_IP ipencap -P in ipsec esp/transport/SITE_A_IP-SITE_B_IP/require;

4. And of course the shared secret.

/usr/local/etc/racoon/psk.txt:

SITE_A_IP    XXXXXXXX

Then of course restart services or do a full reboot.

I prefer route-based tunnels since they work almost like a physical link, and you can use traceroute and standard tools. Your routes decide whats reachable. Policy based tunnels are a bit magic and bypasses standard routing, and I find them hard to troubleshoot.

The theory of operation here is that the tunnel itself gets encrypted, not the specific packets going trough it.

  1. Packet arrives at Site A router. Router makes route lookup and the decision to forward packet to tunnel inteface.
  2. Tunnel encapsulates packet.
  3. Packet then matches Source, Destination and Protocol number defined in IPsec kernel policy (setkey.conf), witch applies the transport encryption.
  4. Encrypted payload leaves router

ifconfig gif0 should display:

gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
    options=80000<LINKSTATE>
    tunnel inet SITE_B_IP --> SITE_A_IP
    inet 192.168.254.2 --> 192.168.254.1  netmask 0xffffffff 
    inet6 fe80::a3d9:9ef1:721c:a309%gif0 prefixlen 64 scopeid 0x4 
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: gif

A tcpdump should show the something like:

19:04:14.700751 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x12), length 136
19:04:15.706837 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x10), length 136
19:04:15.707011 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x13), length 136
19:04:16.715800 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x11), length 136

Good luck!