Public WiFi blocking VPN access

Hi

I’ve just recently set up a IPSec/IKEv2 road warrior VPN but whilst it is working on my Android smartphone / mobile internet connection, it won’t work when I connect to a public WiFi such as at the library.

I read that it might be possible to use port 443 instead but don’t know where such change should be made? I tried adding port 443 to the firewall rule that allows UDP ports 500 & 4500 for my WAN IP but it breaks things working on the mobile internet connection then. I am already using port 443 for the www-ssl service, perhaps this is clashing as it also uses my root domain for a Lets Encrypt cert, whereas my VPN uses a sub domain for the TLS Server & Client certs.

Any help much appreciated.

Regular HTTPS, which is typically permitted, uses TCP port 443. Google’s QUIC protocol used by Google websites and Android browsers uses UDP port 443, so if your VPN client on the mobile uses a single port (normally 4500) during IPsec phase 1 and if the public WiFi permits packets towards UDP port 443 to pass, you might be able to use a dst-nat rule at the Mikrotik to redirect incoming traffic towards UDP port 443 to UDP port 4500.

Otherwise, you would have to switch to an SSTP VPN that uses TCP port 443 at server side, and try whether the library firewall would permit also connections to e.g. port 8443 to resolve the collision with the www-ssl. But once you have a working VPN, you do not need the router to listen for www-ssl on WAN any more, so you can use a dst-nat rule redirecting incoming traffic towards TCP port 443 to TCP port 8443 on WAN.

I am surprized a public Library is blocking standard VPN IPSEC type ports?? Is that normal?
or more likely only allows HTTPS outgoing queries???

Thanks Sindy,

I’m not an expert at Firewall stuff so I queried Copilot with the part about setting up a dst-nat rule and it came up with this:


/ip firewall nat add chain=dstnat action=dst-nat to-addresses= to-ports=4500 protocol=udp dst-port=443

I’m confused by the internal IP bit, since this is the router acting as the VPN server should this IP be my WAN IP or the network that I set up when creating the network address association with the bridge-loopback for the IPsec/IKEv2 road warrior config?

Also, in case it has any baring, I’m using StrongSwan on Android which I can see allows me to change the server port to 443 the connection profile.

All those AI systems learn from existing configurations with little care to subtle details of the context, so don’t take them too literally.

The rule suggested by Copilot addresses the generic case where you set up port forwarding to some server further in your internal network, hence the INTERNAL thing; in your particular case, you don’t need to set to-addresses at all since you only need to change the port. On the other hand, the suggested rule doesn’t care about how the packet got in nor what was its destination address, so it would prevent the Android & Chrome clients in your LAN from connecting to Google websites as it would redirect their requests towards 443 to 4500 as well.

So I would use
/ip firewall nat add chain=dstnat in-interface-list=WAN dst-address-type=local protocol=udp dst-port=443 action=dst-nat to-ports=4500
But this rule assumes that your firewall rules are the default ones, i.e. that interface list WAN is defined and the actual WAN interface is set as a member of that list.

Even more important, did you try in advance that the IKEv2 stack on your mobile indeed sends already the very first packet to port 4500? Because if it doesn’t, the idea won’t work.

Thanks Sindy,

From what I can tell looking at the StrongSwan logs:

If I use the default settings e.g., don’t change the server port it should be using then it looks as though the first packet is sent to port 500 after a line entry ‘[ENC] generating IKE_SA_INIT request 0…’. After quite a bit of cert request stuff it then gets to ‘[IKE] establishing CHILD_SA…’ and ‘[ENC] generating IKE_AUTH request 1…’, followed by splitting the resulting IKE message into fragments and sending the corresponding packets to my WAN IP and port 4500.

I also need to check my default rules because I had to set them up after noticing I didn’t have any IPv4 ones, only IPv6 which I don’t use. I don’t know if this occurred after updating ROS to 7.15.2 or when. I can’t recall where I got the default rules from but they might be outdated. I also have multiple entries in the interface list, which I’m not too sure about:

LAN → bridge1
LAN → ether4 - this is attached to a separate managed switch
WAN → pppoe-out1 - this represents my ISP
WAN —> ether1 - this is where the WAN ethernet cable from my ISP’s modem connects

Having lost the IPv4 firewall is definitely not good, you should disconnect the device from internet ASAP, recreate the firewall (if you don’t have a better source, this is from /system default-configuration print:

/ip firewall nat add chain=srcnat out-interface-list=WAN ipsec-policy=out,none action=masquerade comment="defconf: masquerade"
/ip firewall {
  filter add chain=input action=accept connection-state=established,related,untracked comment="defconf: accept established,related,untracked"
  filter add chain=input action=drop connection-state=invalid comment="defconf: drop invalid"
  filter add chain=input action=accept protocol=icmp comment="defconf: accept ICMP"
  filter add chain=input action=accept dst-address=127.0.0.1 comment="defconf: accept to local loopback (for CAPsMAN)"
  filter add chain=input action=drop in-interface-list=!LAN comment="defconf: drop all not coming from LAN"
  filter add chain=forward action=accept ipsec-policy=in,ipsec comment="defconf: accept in ipsec policy"
  filter add chain=forward action=accept ipsec-policy=out,ipsec comment="defconf: accept out ipsec policy"
  filter add chain=forward action=fasttrack-connection connection-state=established,related comment="defconf: fasttrack"
  filter add chain=forward action=accept connection-state=established,related,untracked comment="defconf: accept established,related, untracked"
  filter add chain=forward action=drop connection-state=invalid comment="defconf: drop invalid"
  filter add chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface-list=WAN comment="defconf: drop all from WAN not DSTNATed"
}

(I’ll come back later regarding the rest)

Thanks Sindy,

The default filter ones match what I had managed to find somewhere. I just have some additional ones that I added as part of the IPSec/IKEv2 VPN setup. These additional ones are added under the following ‘defconf’ ones that you mentioned.

add action=accept chain=input comment=“defconf: accept to local loopback (for CAPsMAN)” dst-address=127.0.0.1

add action=accept chain=input comment=“Allow UDP 500,4500 IPSEC for {MY WAN IP}” dst-address={MY WAN IP} dst-port=500,4500 protocol=udp
add action=accept chain=input comment=“Allow IPSec-esp for {MY WAN IP}” dst-address={MY WAN IP} protocol=ipsec-esp
add action=accept chain=input comment=“IKE2: Allow ALL incoming traffic from {VPN Network CIDR} to this RouterOS” ipsec-policy=in,ipsec src-address={VPN Network CIDR}

add action=drop chain=forward comment=“defconf: drop invalid” connection-state=invalid

add action=accept chain=forward comment=“IKE2: Allow ALL forward traffic from {VPN Network CIDR} to OFFICE network” dst-address={LAN Network CIDR} ipsec-policy=in,ipsec src-address={VPN Network CIDR}
add action=accept chain=forward comment=“IKE2: Allow ALL forward traffic from {VPN Network CIDR} to ANY network” dst-address=0.0.0.0/0 ipsec-policy=in,ipsec src-address={VPN Network CIDR}

My NAT conf:

add action=src-nat chain=srcnat comment=“SRC-NAT IKE2:{VPN Network CIDR} → pppoe-out1 traffic” ipsec-policy=out,none out-interface=pppoe-out1 src-address={VPN Network CIDR} to-addresses={MY WAN IP}
add action=masquerade chain=srcnat comment=“defconf: masquerade” ipsec-policy=out,none out-interface-list=WAN
add action=dst-nat chain=dstnat disabled=yes dst-address-type=local dst-port=443 in-interface-list=WAN protocol=udp to-ports=4500

I updated my ‘defconf: masquerade’ entry as it was missing the comment and the ‘ipsec-policy=out,none’ that you stated in your default one.

All the info. I’ve stated regarding the IPSec/IKEv2 VPN conf. came from the MUM presentation from 2019 apart from the last NAT entry which we were discussing earlier in relation to port 443 as a work around to public WiFi blocking.

RE: https://mum.mikrotik.com/presentations/MY19/presentation_7008_1560543676.pdf

Sorry, I was in a hurry, I haven’t noticed that you have already recreated the IPv4 firewall “somehow”. So I’ve suggested disconnection from the internet until you would recreate it because the “filth from the 'net” is incredibly fast to squat in if you let it.

As for the VPN… the thing is that I could not find a way how to tell Strongswan to what port to switch once it detects NAT. So when you configure it to use port 443, it only affects where it will send the initial packets instead of the default port 500, but as soon as it detects NAT, it will switch to 4500.

So I’m afraid that there is no simple way - you would have to convince the Strongswan team to do what Mikrotik does, i.e. to use a single port for IKEv2 at all stages (which is possible due to the fact that IKEv2 responders MUST accept initial packets on 4500), which allows the custom setting of the responder port to stay valid also after NAT has been detected.

So you’ll apparently have to choose between SSTP (which has its drawbacks but should work from anywhere where you can browse the web) and Wireguard (which has its own limitations but can work using any single UDP port).

Another possibility is to carry around a mAP lite that would connect to the public WiFi as a client and act as an AP for your phone, but such a solution it is not exactly elegant.

So I did some more digging…

I found this conversation about StrongSwan and the way it reads to me is that you only need to specify a different port instead of the default 500.

https://wiki.strongswan.org/issues/2344

So I moved the NAT entry that you suggested to the top of that list and now my mobile can connect on port 443. I didn’t change the ‘www-ssl’ service, that is still also on 443 but tcp I believe. I think tcp and udp can coexist on the same port from what I’ve read.

It still isn’t quite there, compared to connecting on the default ports though…

I’m seeing some ‘esp sequence verification failed’ messages in StrongSwan. These increase when I open the browser on the phone and navigate to some web page. I also see a couple of config lines mentioning ‘handling INTERNAL_IP4_NETMASK attribute failed’ and ‘handling INTERNAL_IP4_SUBNET attribute failed’, but not sure if these were occurring when not overriding the port to 443.

Is the esp issue related to protocol 50? Do I need a NAT rule or something for the ipsec-esp protocol which I assume relates to protocol 50?

The port numbers in UDP and TCP are indeed unrelated. “Coexistence” is not the word I would choose but it is one way to describe it.


Indeed. An unusual approach to me (apparently not only to me), but OK. My imagination wasn’t wild enough to anticipate such an approach so I did not take the effort to let the responder actually respond when I was testing the manual configuration of server side port in Strongswan for Android yesterday.


The ESP protocol (IP protocol number 50) has no notion of ports, hence it is not well suited for traversing NATs; that’s why NAT presence is detected during Phase 1 and if found, the peers switch to encapsulating ESP into UDP. It would be quite rare, although not impossible, that you got a public IP in a library, so I’d rather assume that the ESP gets encapsulated into UDP to port 443 in this case.

So if you haven’t yet, make your test environment similar to the library one, i.e. use the mobile data of the phone rather than its WiFi to connect to the Mikrotik responder so that you are sure the NAT is there.

Thanks Sindy,

I’ve been testing with my mobile data as it saves me a trip to the library at the moment.

I removed port 443 from the settings in StrongSwan but I get the same issues showing in the StrongSwan log as I mentioned in my previous message.

Any ideas what I should check / try next please?

EDIT: just seen in the StrongSwan log that it mentions this:

[CFG] selected proposal ESP:AES_GCM_16_256/NO_EXT_SEQ

Is it maybe not picking the most suitable encryption algorithm from the MT IPsec proposal?

The various ESP sequence number verification failed messages show various sequence numbers when referring to the source and destination IP after reference to an SPI string value and so it’s not as though the sequence numbers aren’t there. I thought perhaps that was what the NO_EXT_SEQ above might be eluding to.

I can’t say more without seeing the ipsec logs at least from the Mikrotik, even better also from the Strongswan.

On Mikrotik:
/system logging add topics=ipsec,!packet
/log print follow-only file=ipsec-start where topics~“ipsec”

Then press the VPN profile item in the Strongswan list on the phone to initiate a connection attempt.
After 20-30 seconds, press Ctrl-C in the window where the /log print … is running, cancel the connection attempt on the phone, download the file ipsec-start.txt from the Tik, use the Find&Replace function of your favorite text editor to systematically replace your public IP by my.tik.pub.ip if it bothers you, or even do the same for the NAT address of the phone, and post the contents of the modified file between [code] and [/code] tags or as a file attachment.

Also post the output of /ip ipsec export verbose, again redact the IP if it is shown in the output and it bothers you. Certificate name and contents is also not important for the analysis, so you can redact that in the log file too.

at the places where i’m living , i think that this is common around the world, all the public internet (hotspot) such a library and airport are blocking all the ports except 443.

OpenVPN, SSTP or ZeroTier in this ase are perfect scenario.

l2pt/ipsec is nice and easy to set up,but unuseful in this case.

Hi Sindy,

I’ve carried out the test you suggested, for this I didn’t override the port with 443 in StrongSwan so it’s using ports 500 & 4500. This was done using the mobile providers data connection so that the test is against the WAN interface of the MT. I can supply the same test using port 443 if required?


/ip ipsec export verbose

2024-07-24 16:57:33 by RouterOS 7.15.2

software id = I87D-7LGC

model = RB750Gr3

serial number = {REDACTED}

/ip ipsec mode-config
set [ find default=yes ] name=request-only responder=no use-responder-dns=exclusively
add address-pool=“pool {REDACTED - my.vpn.domain}” address-prefix-length=32 name=“modeconf {REDACTED - my.vpn.domain}” split-dns=“” split-include=0.0.0.0/0 static-dns={REDACTED - my.vpn.DNS} system-dns=no
/ip ipsec policy group
set [ find default=yes ] name=default
add name=“group {REDACTED - my.vpn.domain}”
/ip ipsec profile
set [ find default=yes ] dh-group=modp2048,modp1024 dpd-interval=2m dpd-maximum-failures=5 enc-algorithm=aes-128,3des hash-algorithm=sha1 lifetime=1d name=default nat-traversal=yes proposal-check=obey
add dh-group=modp2048,modp1536,modp1024 dpd-interval=2m dpd-maximum-failures=5 enc-algorithm=aes-256,aes-192,aes-128 hash-algorithm=sha256 lifetime=1d name=“profile {REDACTED - my.vpn.domain}” nat-traversal=yes proposal-check=obey
/ip ipsec peer
add disabled=no exchange-mode=ike2 local-address=my.tik.pub.ip name=“peer my.tik.pub.ip” passive=yes profile=“profile {REDACTED - my.vpn.domain}” send-initial-contact=yes
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=sha1 disabled=no enc-algorithms=aes-256-cbc,aes-192-cbc,aes-128-cbc lifetime=30m name=default pfs-group=modp1024
add auth-algorithms=sha512,sha256,sha1 disabled=no enc-algorithms=aes-256-cbc,aes-256-ctr,aes-256-gcm,aes-192-ctr,aes-192-gcm,aes-128-cbc,aes-128-ctr,aes-128-gcm lifetime=8h name=“proposal {REDACTED - my.vpn.domain}” pfs-group=none
/ip ipsec identity
add auth-method=digital-signature certificate={REDACTED - my.vpn.domain} comment={REDACTED - my.vpn.client.email.id(2)} disabled=no generate-policy=port-strict match-by=certificate mode-config=“modeconf {REDACTED - my.vpn.domain}” peer=“peer my.tik.pub.ip” policy-template-group=“group {REDACTED - my.vpn.domain}”
remote-certificate={REDACTED - my.vpn.client.email.id(2)} remote-id=fqdn:{REDACTED - my.vpn.client.email.id(2)}
add auth-method=digital-signature certificate={REDACTED - my.vpn.domain} comment={REDACTED - my.vpn.client.email.id(1)} disabled=no generate-policy=port-strict match-by=certificate mode-config=“modeconf {REDACTED - my.vpn.domain}” peer=“peer my.tik.pub.ip” policy-template-group=“group {REDACTED - my.vpn.domain}”
remote-certificate={REDACTED - my.vpn.client.email.id(1)} remote-id=user-fqdn:{REDACTED - my.vpn.client.email.id(1)}
/ip ipsec policy
set 0 disabled=no dst-address=::/0 group=default proposal=default protocol=all src-address=::/0 template=yes
add comment={REDACTED - my.vpn.domain} disabled=no dst-address={REDACTED - my.vpn.network}/24 group=“group {REDACTED - my.vpn.domain}” proposal=“proposal {REDACTED - my.vpn.domain}” protocol=all src-address=0.0.0.0/0 template=yes
/ip ipsec settings
set accounting=yes interim-update=0s xauth-use-radius=no

I’ve used the following strings to redact the above and the files (please find attached) as appropriate, ‘{REDACTED}’ on its own was used where it seemed enough context was present preceding this value:

my.tik.pub.ip
{REDACTED - my.phone.ip}
{REDACTED}
{REDACTED - my.vpn.client.email.id}*
{REDACTED - subject key id}
{REDACTED - authority key id}
{REDACTED - my.crl.domain}
{REDACTED - my.allocated.ip.from.vpn.pool}
{REDACTED - my.vpn.domain}
{REDACTED - my.vpn.DNS}
{REDACTED - my.vpn.network}

  • this one differs in the conf. above as I have two identities set up in MT IPSec, so I’ve appended an index in brackets, but the test was only done with one, which was when I created the redaction values above

Thank you for taking the time to look into this for me.
1st strongSwan 2.5.1 Log File redacted.txt (30.7 KB)
ipsec-start-redacted.txt (47.2 KB)

Makes this more and more interesting.
http://forum.mikrotik.com/t/amneziawg-in-routeros/175150/12

I have mixed feelings about the outcome… you have clearly let the connection attempt last longer than 20-30 seconds as I have suggested, which is actually good as it has revealed that it “almost worked”, or maybe worked completely, hard to say. There is definitely some mutual misunderstanding where Mikrotik keeps retransmitting a set of “type 1” messages whereas the Strongswan keeps ignoring them, claiming received message ID 1, expected 2, ignored, but as it later just occasionally reports a missing packet, it feels as if it actually started working. At least they have reached an agreement on both Phase 1 and Phase 2 proposals.

The thing is that the Strongswan log doesn’t mention any external impulse causing the termination of the connection, so did the Strongswan GUI present the connection as successful and you have terminated it manually, or did Strongswan give up on its own? If the former, can you try again and ping something in your LAN from the phone (given that you have restricted the Mikrotik side of the policy to only the LAN subnet) while the connection is shown as up?

Hi Sindy,

The first test didn’t last long enough so I reran it because I also wanted to open the Chrome browser on the mobile and navigate to a web site. I think the esp sequence verification errors only happen when actually making use of the connection, hence using the browser. These start to show up on line 253 (or 215, more on this below) of the StrongSwan log file.

The connection appeared to be established correctly according to the UI in StrongSwan and I terminated it from the StrongSwan UI.

It appears the problem starts on line 699 of the MT log, received 1364 bytes from phone, which was probably the browser request of some sort, whether an open tab fetching data upon browser open or my web page request I don’t know without retesting. Anyway, this seems to have surfaced the esp sequence number verification failures which look as though they start from line 702 (MT log) where the same byte size transmissions begin repeating in 6 blocks, 1220, 1140 & 468 bytes. However, after each of these log lines the debug from MT states that a transmission 4 bytes larger will be sent to the phone. The phone however only seems to log an issue with the smaller of each transmission (starting line 215). If you ignore the anomaly of line 247 in the StrongSwan log where a duplicate of a 1220 byte transmission occurs then there are 18 lines of these received transmissions (received message ID 1, expected 2, ignored). The number of ‘ESP sequence number verification failed’ lines, starting from line 253 is also 18.

Is there a reason why each payload would be sent with and without 4 extra bytes? The lesser of which clearly seems to be received as evidenced by the StrongSwan log concurring on the smaller byte sizes (lines 215 through to 253 inclusive) unless it’s making a subtraction of the sequence number byte size of course. Perhaps each payload with the extra 4 bytes is also being received by the phone and that was why the web browsing worked? Assuming here that StrongSwan is only writing what it believes are issues to the log and not good transmissions taking place once the connection (phase 2) has been established.

Also, maybe line 211 of StrongSwan log, ‘selected proposal: ESP:AES_GCM_16_256/NO_EXT_SEQ’, maybe this is referring to the sequencing but I don’t know why this proposal is being chosen.

Perhaps the test should be rerun with packets being captured in the MT log to establish whether each payload (post phase 2) is actually being transmitted twice (2 versions, with and without 4 extra bytes)?

The Mikrotik log (and to what I remember, the StrongSwan log as well) completely ignores Phase 2 transport packets, so that 1364 byte packet was part of IKEv2 negptiation.


I can’t speculate about the reason of this difference, it may be the SPI or the sequence number as both are 32-bit fields.


NO_EXT_SEQ is just an indication that extended sequence numbers have not been negotiated. As for “why”, a proposal that both parties support is normally chosen. I never bothered to dive deep into the criteria used when multiple proposals are supported by both - common sense says it should be the one with the “best” encryption but it’s not that easy - the perception of security may change over time if an alghoritm gets cracked, the overhead is different…


A good idea, but I’m not sure it will help understand why Strongswan does not like those “type 1” packets. So when doing the test, I’d also like to have the connection stay up for 5 minutes and ping the LAN address from the phone during that time, so that we saw whether the encrypted pings are being sent using the Phase 2 SA or not.

Hi Sindy,

I changed the previous logging entry so that packets were not excluded and ran the same command in ROS terminal to output the ipsec-start file but it doesn’t seem to have as much in it as I thought it would have. Should I have used a different terminal command to this one?


/log print follow-only file=ipsec-start where topics~“ipsec”


I’ve just attached this file for now in case I need to rerun the test.

Around 15:43 UK time in the log I switched to a network app on the phone (PingTools) and attempted to ping my PC on my LAN using tcp protocol and default of port 80. All 3 packets were sent but received no reply according to PingTools. I tried this twice, the second time I targeted the first address of my LAN address block e.g. 192.168.1.0, also no reply.

I also terminated the ROS terminal window first this time.
ipsec-start with packets redacted.txt (118 KB)