Mikrotik: SSTP and web server on the same port

I was thinking, why not set up a home SSTP server? This type of VPN runs on port 443 and doesn’t attract too much attention. There’s just one problem. Port 443 is already taken, and I absolutely don’t want to give it to the VPN server. And then I remembered port knocking.

The term «port knocking» refers to a scenario where a remote machine «knocks» on a specific port in a pre-arranged manner. This communicates its address and intention to connect to a private service (such as our SSTP service). The server, in turn, allows the remote machine to do so.

And now the practical part.

First, we need to determine the conditions for the «tapping.» This is entirely up to your imagination. But, in my opinion, the ideal option would be to tap on port 443. This will minimize the «suspiciousness» of this activity.

As it turns out, RouterOS makes this extremely easy (as always ;)). Go to IP > Firewall > Mangle and create a rule:

 /ip firewall mangle add chain=prerouting protocol=tcp dst-port=443 content="tuktuktuk" action=add-src-to-address-list address-list="sstp-in" address-list-timeout="00:01:00" 

The idea here is that, one way or another, the sni header can be easily extracted from the HTTPS request. The «password» itself will be transmitted as a domain name (for example, tuktuktuk.ex.uz). As soon as our tick receives a GET request for this domain name, it will create an entry in the firewall’s src list. We’ll use this entry in the dstnat rule:

 /ip firewall nat add action=dst-nat chain=dstnat dst-address-list=\
    "router interfaces" dst-port=443 protocol=tcp src-address-list=!sstp-in \
    to-addresses=192.168.88.123 

Thus, we will forward all connections to port 443 on the web server 192.168.88.123, except for those that came from addresses from the sstp-in list.
For the latter, this rule does not work and they will go directly to the Mikrotik SSTP server.

Setting up the client

Now, on the client side, you need to add a task to the schedule. It will periodically send requests, updating its dynamic address in the server’s src list. Incidentally, entries are added there with a one-minute timeout.

The easiest option is to go to system > Scheduler and add a task with a 1-minute interval using the command line:

 /tool fetch url=https://tuktuktuk.ex.uz/ mode=https keep-result=no 

It is important to know that the specified domain name must either actually exist or at least be locally registered in the client’s DNS.

Well, if you don’t want to send extra requests, you can make the shedaler script like this:

 {
:if ([/interface get sstp-out running]=true) \
do={
 :log info "SSTP interface running. skeep knocking"
} \
   else={[/tool fetch url=https://tuktuktuk.ex.uz/ mode=https keep-result=no]}
}