IPSec misconfiguration

Folks, my IPSec configuration using digital signatures auth-method is showing connection established, but no intalled SA's. I am simulating this between two CHR's in virtual environment. Can you assist me to t-shoot?

Here's my configuration.

(I have external static DNS entries to enable hostnames between vpn.site1.net and vpn.site2.net to resolve.)

Server peer

/certificate add name=root-ca common-name=TEST-CA days-valid=3650 digest-algorithm=sha256 key-size=4096 key-usage=digital-signature,key-encipherment,data-encipherment,key-cert-sign,crl-sign organization=TESTING unit=IT trust-store=ipsec,radius trusted=yes
/certificate sign root-ca
/certificate add name=vpn-cert-server common-name=vpn.site1.net subject-alt-name="DNS:vpn.site1.net" days-valid=365 digest-algorithm=sha256 key-size=4096 key-usage=tls-server organization=TESTING unit=IT trust-store=ipsec,radius trusted=yes
/certificate add name=vpn-cert-client common-name=vpn.site2.net subject-alt-name="DNS:vpn.site2.net" days-valid=365 digest-algorithm=sha256 key-size=4096 key-usage=tls-client organization=TESTING unit=IT trust-store=ipsec,radius trusted=yes

/certificate sign ca=root-ca vpn-cert-server
/certificate sign ca=root-ca vpn-cert-client
/certificate export-certificate vpn-cert-client type=pkcs12 export-passphrase=12345678

Client peer

/certificate import file-name=XXXX.p12 name=vpn-cert-client password=12345678
/certificate set [find where common-name="TEST-CA"] name="root-ca"
/certificate set [find where common-name="vpn.site2.net"] name="vpn-cert-client"

Server peer

/interface bridge add bridge=site1-vpn-lo port-cost-mode=short protocol-mode=none
/ip address add address=172.254.1.1/24 interface=site1-vpn-lo network=172.254.1.0

/ip firewall filter add action=accept chain=input dst-port=500,4500 protocol=udp
/ip firewall filter add action=accept chain=output dst-port=500,4500 protocol=udp
/ip firewall filter add action=input protocol=ipsec-esp
/ip firewall filter add action=accept chain=forward ipsec-policy=in,ipsec
/ip firewall filter add action=accept chain=forward ipsec-policy=out,ipsec
/ip firewall nat add action=src-nat chain=srcnat dst-address=172.254.1.2 to-addresses=172.254.1.1 place-before=0

/ip ipsec mode-config add name=vpn-site2 responder=yes
/ip ipsec policy group add name=site2-vpn
/ip ipsec profile add dh-group=ecp256 dpd-interval=30s dpd-maximum-failures=3 enc-algorithm=aes-256,aes-128 hash-algorithm=sha256 name=site2-vpn nat-traversal=no
/ip ipsec peer add exchange-mode=ike2 name=vpn.site2.net profile=site2-vpn passive=yes
/ip ipsec proposal add auth-algorithms=sha256 enc-algorithms=aes-256-cbc,aes-128-cbc name=site2-vpn pfs-group=none
/ip ipsec identity add auth-method=digital-signature certificate=vpn-cert-server generate-policy=port-strict match-by=certificate mode-config=vpn-site2 peer=vpn.site2.net policy-template-group=site2-vpn remote-certificate=vpn-cert-client
/ip ipsec policy add dst-address=172.254.1.2/32 group=site2-vpn proposal=site2-vpn src-address=172.254.1.1/32 template=yes

Client peer

/interface bridge add bridge=site2-vpn-lo port-cost-mode=short protocol-mode=none
/ip address add address=172.254.1.2/24 interface=site2-vpn-lo network=172.254.1.0

/ip firewall filter add action=accept chain=input dst-port=500,4500 protocol=udp
/ip firewall filter add action=accept chain=output dst-port=500,4500 protocol=udp
/ip firewall filter add action=input protocol=ipsec-esp
/ip firewall filter add action=accept chain=forward ipsec-policy=in,ipsec
/ip firewall filter add action=accept chain=forward ipsec-policy=out,ipsec
/ip firewall nat add action=src-nat chain=srcnat dst-address=172.254.1.1 to-addresses=172.254.1.2 place-before=0

/ip ipsec mode-config add name=vpn-site1 responder=no
/ip ipsec policy group add name=site1-vpn
/ip ipsec profile add dh-group=ecp256 dpd-interval=30s dpd-maximum-failures=3 enc-algorithm=aes-256,aes-128 hash-algorithm=sha256 name=site1-vpn nat-traversal=no
/ip ipsec peer add address=vpn.site1.net exchange-mode=ike2 name=vpn.site1.net profile=site1-vpn send-initial-contact=no
/ip ipsec proposal add auth-algorithms=sha256 enc-algorithms=aes-256-cbc,aes-128-cbc name=site1-vpn pfs-group=none
/ip ipsec identity add auth-method=digital-signature certificate=vpn-cert-client remote-certificate=none generate-policy=port-strict peer=vpn.site1.net policy-template-group=site1-vpn
/ip ipsec policy add dst-address=172.254.1.1/32 group=site1-vpn proposal=site1-vpn src-address=172.254.1.2/32 template=yes

I have been trying this for some time. During this exercise I have stumbled into many different errors.

/system/logging/add topics=ipsec,!packet
/log print follow-only where topics~"ipsec"

The NAT rules and output filter ones aren't needed, NAT traversal should be set to yes on both profiles and the policies should be configured as follows:

Server:

/ip ipsec policy
add dst-address=172.254.1.0/24 group=site2-vpn proposal=site2-vpn src-address=0.0.0.0/0 template=yes

Client:

/ip ipsec policy
add group=site1-vpn proposal=site1-vpn template=yes

To access subnets of the server through the client/s* and vice versa, they should be added as split-include entries in the mode config of the appropriate device

*Windows devices don't accept split-include subnets, Apple devices only accept the first one

As for your other questions from the other topics, in practice "site-to-site" is just "roadwarrior" with a router as a client, as you correctly assumed, and transport mode is only used for communication between the peers on the VPN subnet, whereas tunnel mode allows traffic between remote subnets (achieved via split-include in mode configs or static tunnel policies)

Thanks for the feedback. Unfortunately, still seems Phase 2 fails as no installed SAs present. Active-peer showing established.

Also:

Server:

/ip ipsec policy
add dst-address=172.254.1.0/24 group=site2-vpn proposal=site2-vpn src-address=0.0.0.0/0 template=yes

Whenever 0.0.0.0/0 is in the policy, I understand this to mean "all traffic". So does this policy mean "all traffic on server to 172.254.1.0/24"?

Client:

/ip ipsec policy
add group=site1-vpn proposal=site1-vpn template=yes

Why isn't src-address or dst-address configured in the policy on the client?

To access subnets of the server through the client/s* and vice versa, they should be added as split-include entries in the mode config of the appropriate device

Do you mean in the mode-config on the server?

As for your other questions from the other topics, in practice "site-to-site" is just "roadwarrior" with a router as a client

Then what I'm trying to configure is site-to-site, but I don't want the client (remote router) to route all its traffic over the IPSec tunnel. Client will only need to reach some services in the server's DMZ. This brings me to another question about DNS configuration:

  • how do you ensure private hostnames on IPSec server (e.g. myhost.dmz.internalregistered in static DNS cache by DHCP script) are correctly resolved by client over IPSec tunnel? Does the IPSec server send the DNS IP to the client by mode-config and does this override any other DNS server configured on the client (until the IPSec tunnel ends) ? Does this only happen when server's mode-config responder=yes? Or can client still make use of server for DNS so long as client's mode-config hasuse-responder-dns=yes/exclusively? Which combination of these options are needed?

transport mode is only used for communication between the peers on the VPN subnet

Can you suggest a practical use-case/example? Do you mean the IKE daemons? E.g. in my configuration, the two peers on the 172.254.1.0/25 network?

Quite the contrary, the established flag of fhe peer means both phases were negotiated. Something else is incorrectly configured. That's why a config export posted here would be a good idea:

export file=anynameyouwish

Typically it means that, but since we're talking about a template, the dynamically generated policy will change the dst-address to the client's one from the VPN subnet and will mean "all traffic destined to the client, be encrypted"

Because it's a template and the dynamically generated policies will have different dst-addresses depending on the supplied subnets by the server's mode config.

Yes, and it reminded that for client subnets to access the server ones, an address list should be created on the client and added to its mode config:

/ip firewall address-list
add address=x.x.x.x list=local
/ip ipsec mode-config
set [ find name=site1-vpn ] src-address-list=local

You have it correctly figured out: responder=yes regardless of DNS for the server mode config but static-dns set to its VPN address and allow-remote-requests set to yes in /ip/dns, and use-responder-dns=yes/exclusively on client mode config.

In your case, none

A quick question, though. Why don't you set up Wireguard. It's a fair bit easier to configure because it has a virtual interface unlike this IPsec implementation, that can be used in routes, firewall rules, etc.

Both are important VPN technologies. It is worthwhile learning both.

I have turned on ipsec debugging and can see an error on the client (doesn't show on the server):

ipsec,info,account per authorized: vpn.site1.net ...
ipsec got error: TS_UNNACEPTABLE.

Can't find an explanation for this online anywhere though.

Was able to find this explanation suggesting it is due to mismatch in policies.

Typically it means that, but since we're talking about a template, the dynamically generated policy will change the dst-address to the client's one from the VPN subnet and will mean "all traffic destined to the client, be encrypted"

In WinBox when you select template=yes in policy, the GUI hides some options that are present when this box isn't ticked, such as tunnel=yes/no. How does setting the policy to template know whether to use tunnelling or transport? Why do we select template in the first place? What is its advantage? If it's basically about dynamic generation of policies, what is the non-template equivalent, i.e. to explicitly create the correct policy for the connection?

Because it's a template and the dynamically generated policies will have different dst-addresses depending on the supplied subnets by the server's mode config.

If I was to use template=no on the server, what is the correct policy for the client?

for client subnets to access the server ones, an address list should be created on the client and added to its mode config

So if I have a bridge on the client with two VLANs each on a 192.168.99.0/25 subnet, and one host per subnet; and if I have a bridge on the server with two VLANs each on a 192.168.50.0/25 subnet, and one host per subnet, then the hosts on the client's subnets could reach the two hosts on the server's subnets if the address-list you suggest on the client includes the 192.168.50.0/24 network attached to the client's src-address-list in its mode-config?

OK, solved it. The hint in the link regarding the reason for TS_UNNACEPTABLE error was useful. Instead of:

Client:

/ip ipsec policy
add group=site1-vpn proposal=site1-vpn template=yes

I created the followng:

/ip ipsec policy add src-address=172.254.1.0/24 dst-address=172.254.1.0/24 peer=vpn.site1.net tunnel=yes proposal=site1-vpn ipsec-protocols=esp action=encrypt

Now the SA's are present. However, I do see some "errors" on the server regarding templates/policies:

ipsec searching for policy for selector: ...
ipsec no template matches
ipsec,error no policy found/generated

No similar output on client. A dynamic policy is created on the server which I don't believe is what I want if I want the server controlling configurations for clients, right?

Still, any questions in previous posts would be helpful to know too!

I wanted to suggest to you a more dynamic approach, alas it doesn't work as expected. Therefore I would change to the more robust approach and my typical modus operandi: static policies. The template policy on the server you can keep as I suggested, but you would need two additional ones: one on server, one on client:

Server:

/ip ipsec policy
add action=encrypt dst-address=192.168.99.0/25 level=unique peer=vpn.site2.net proposal=site2-vpn src-address=192.168.50.0/25 tunnel=yes

Client:

/ip ipsec policy
add action=encrypt dst-address=192.168.50.0/25 level=unique peer=vpn.site1.net proposal=site1-vpn src-address=192.168.99.0/25 tunnel=yes

No need for split-include in the mode config then.

As for NAT (the reason for address lists on the client), the default masquerade rule contains a very important matcher that, combined with static policies, renders the need for said address lists useless: ipsec-policy=out,none. Make sure that you have it.

This brings me to my next question about VLANs: how can two VLANs per subnet reside on the same subnet? That should be considered a misconfiguration, so please elaborate a bit more on this aspect of your setup

I just checked my physical network and I have indeed got distinct networks per VLAN (yes some networks are subnetted but no subnets of same network spanning different VLANs). So this was a brain fart when writing the post and setting up in virtual environment only.

However, don't VLANs separate at L2 (reduce size of broadcast domains) not L3, so why does it matter?

Yes, VLANs do separate at L2 but proper L3 communication is needed as well (DHCP, DNS, etc.) and that's where VLAN interfaces come in play: they operate on L3 together with L2 bridge VLAN filtering to allow, e.g. DHCP servers to run or to filter inter-VLAN traffic at L3 (firewall)

Are these extra policies needed if:

  • a GRE tunnel is configured over 172.254.1.0/24 for both sides,
  • static entries in each peer's routing table pointing to the other end's subnet via the GRE interface as gateway

Such as...

Server

/interface/gre/add allow-fast-path=no local-address=172.254.1.1 name=site1-gre remote-address=172.254.1.2

/ip/route/add dst-address=192.168.XX.0/24 gateway=site1-gre

Client

/interface/gre/add allow-fast-path=no local-address=172.254.1.2 name=site1-gre remote-address=172.254.1.1

/ip/route/add dst-address=192.168.YY.0/24 gateway=site2-gre

Nope.

For future readers, these errors were resolved by the static policy. This setup works for GRE/IPSec. Just need to put the GRE tunnel endpoints as the IPSec local/remote endpoints, give the GRE a static IP, then add static routes to/from subnets using the GRE interface as gateway (not its IP for me).