I have a hub/spoke VPN setup using three routers with the above version. Most of the time it works OK but on occasions when the link comes up it seems to bypass the IPSEC encrytption:
If I clear the connection on the hub (l2tp server) it comes back in the same connected state. If I go to the client, disable then enable the l2tp-client, it re-establishes and works correctly. This behavior isn’t always repeatable but it’s usually after I power up the routers.
Yes I have seen this happen as well. When the IPsec does not succeed for some reason the L2TP
still proceeds and the traffic is not encrypted. You can avoid this with suitable firewall rules.
/ip firewall filter
add action=reject chain=input comment=\
"reject unprotected L2TP even when established!" dst-port=1701 \
ipsec-policy=in,none protocol=udp reject-with=icmp-admin-prohibited
This rule has to be before the established/related rule in the input chain.
Of course it is always good to allow port 1701 only via IPsec in the input firewall:
(this can be further down in the list below established/related matching)
It is not sufficient to prevent the problem because when there is an existing L2TP/IPsec link
between two routers, then one is rebooted, it can happen that the L2TP comes back unprotected
and is matched by the existing connection tracking entry and thus by established/related, that
is why you need the first rule as well.
I’ve modified the firewall rules to implement this. I’d just adapted the default firewall adding two rules to permit ESP and permit UDP 500,4500,1701 from the spoke routers (O2 UK broadband address range). Firstly I removed port 1701, which was intersting to see the IPSEC come up but no L2TP established. I then added the new rules and the L2TP came back up.
[admin@O2vpn-hub] > /ip firewall filter print
Flags: X - disabled, I - invalid, D - dynamic
0 D ;;; special dummy rule to show fasttrack counters
chain=forward action=passthrough
1 ;;; defconf: accept ICMP
chain=input action=accept protocol=icmp log=no log-prefix=""
2 chain=input action=accept protocol=ipsec-esp src-address=82.132.160.0/20
in-interface=ether1 log=no log-prefix=""
3 chain=input action=accept protocol=udp src-address=82.132.160.0/20
in-interface=ether1 dst-port=500,4500 log=no log-prefix=""
4 ;;; reject unprotected L2TP even when established!
chain=input action=reject reject-with=icmp-admin-prohibited protocol=udp
src-address=82.132.160.0/20 dst-port=1701 ipsec-policy=in,none
5 chain=input action=accept protocol=udp src-address=82.132.160.0/20
dst-port=1701 log-prefix="l2tp" ipsec-policy=in,ipsec
6 ;;; defconf: accept establieshed,related
chain=input action=accept connection-state=established,related log=no
log-prefix=""
I’ll just give it another tweak to log any rejected unoprotected L2TP so I can see how often it occurs.
It is most efficient to move the established/related rule up as much as possible. Even the ICMP rule can be below that.
The rules are evaluated top to bottom and you want the established/related rule to hit as quick as possible, all rules
below that will be evaluated only once for each new connection.
And remember you have no real firewall unless you drop some traffic, as the default is to accept.
Normally there is some rule near the end that drops everything from ether1 so all unexpected incoming traffic from
internet is dropped. Actually I prefer instead to put an accept rule for traffic from the LAN and a drop rule for everything
at the end. Be careful not to lock yourself out when you experiment, use “safe mode”.
I do have a drop rule, just posted the relevant stuff above to show the input chain. I can drag the rules around in winbox to optimise things. If I add a rule dropping everything apart from the LAN won’t that block traffic from the l2tp connections as they appear as interfaces?
Yes, but normally you would not do input from those, only forwarding.
You can keep the explicit drop as long as you understand what you are doing.
E.g. when your internet is via PPPoE the explict drop should be on the PPPoE interface, not the ether1 interface.
That is where lots of people go wrong.
So now I’ve re-ordered a few rules based on your suggestions, traffic flow etc. Most of my understanding is based on experience with Cisco ACLs, ip inspect rules and some BSD pf. Cisco ACL has an implied deny-all at the bottom of the list, so need to double check I’ve done that on Mikrotik!
[admin@O2vpn-hub] > /ip firewall filter print
Flags: X - disabled, I - invalid, D - dynamic
0 D ;;; special dummy rule to show fasttrack counters
chain=forward action=passthrough
1 ;;; reject unprotected L2TP even when established!
chain=input action=reject reject-with=icmp-admin-prohibited protocol=udp src-address=82.132.160.0/20 in-interface=ether1
dst-port=1701 log=no log-prefix="" ipsec-policy=in,none
2 ;;; defconf: accept establieshed,related
chain=input action=accept connection-state=established,related in-interface=ether1 log=no log-prefix=""
3 chain=input action=accept protocol=ipsec-esp src-address=82.132.160.0/20 in-interface=ether1 log=no log-prefix=""
4 chain=input action=accept protocol=udp src-address=82.132.160.0/20 in-interface=ether1 dst-port=1701 log=no log-prefix="l2tp"
ipsec-policy=in,ipsec
5 chain=input action=accept protocol=udp src-address=82.132.160.0/20 in-interface=ether1 dst-port=500,4500 log=no log-prefix=""
6 ;;; defconf: accept ICMP
chain=input action=accept protocol=icmp log=no log-prefix=""
7 ;;; defconf: drop all from WAN
chain=input action=drop in-interface=ether1 log=no log-prefix=""
8 ;;; defconf: fasttrack
chain=forward action=fasttrack-connection connection-state=established,related log=no log-prefix=""
9 ;;; defconf: accept established,related
chain=forward action=accept connection-state=established,related log=no log-prefix=""
10 ;;; defconf: drop invalid
chain=forward action=drop connection-state=invalid log=no log-prefix=""
11 ;;; defconf: drop all from WAN not DSTNATed
chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface=ether1 log=no log-prefix=""
And here are the stats after it’s been running for 24 hours -
[admin@O2vpn-hub] > /ip firewall filter print stats
Flags: X - disabled, I - invalid, D - dynamic
# CHAIN ACTION BYTES PACKETS
0 D ;;; special dummy rule to show fasttrack counters
forward passthrough 113 549 020 142 542
1 ;;; reject unprotected L2TP even when established!
input reject 904 18
2 ;;; defconf: accept establieshed,related
input accept 59 096 572 397 885
3 input accept 46 461 904 60 136
4 input accept 32 634 008 47 988
5 input accept 16 605 124 20 734
6 ;;; defconf: accept ICMP
input accept 4 018 56
7 ;;; defconf: drop all from WAN
input drop 235 019 1 684
8 ;;; defconf: fasttrack
forward fasttrack-connection 46 893 729 68 934
9 ;;; defconf: accept established,related
forward accept 46 893 729 68 934
10 ;;; defconf: drop invalid
forward drop 229 5
11 ;;; defconf: drop all from WAN not DSTNATed
forward drop 0 0
I can see from the stats that a few unprotected L2TP connections have been rejected.
Mikrotik access lists are similar to Cisco ACL in that they are processed from top to bottom and that you want
to have the common cases as near to the top as possible. But they are also much more powerful, because they
allow you to make branches that make some broad match and then jump to another list that does more detailed
matching for that case. And it is also very useful that you can put comments at every rule. Linux would allow
a default-deny policy but apparently MikroTik has chosen not do do that. It is however easy to add a deny rule
at the end of every list, with the benefit that you get statistics and can do logging.
(of course not a good idea for an internet traffic dropping rule, but I normally use this for LAN rules where any
traffic being dropped at the end of the list points to potential problems)
The hits that you now see may not be all from your own environment, there may be “portscanners” on the
internet that try to send traffic to port 1701. With your previous setup you would not have seen these as a
separately counted item, but they would still be blocked by a “drop everything from internet” rule.