[ROS7] How to get public IP (sort of)

TL;DR

Get a cloud VM with public IP, host wireguard server on it, connect to it from Mikrotik router, port forward everything from VM to Mikrotik via wireguard tunnel.

Other notes:

  • Linode provider offers cheapest instance for 5$/month and you get 4TB of monthly TX data. RX data is not counted (free).
  • ip/cloud assigned ddns no longer works. Consider using your own domain or free DDNS duckdns.org.
  • By using below method you won’t be able to use ports 22/tcp and 51820/udp (they can be changed tho).

Use-case

Your ISP (so basically anyone who lives on mobile data) does not have public IP and therefore cannot host anything on their home network. My specific use case was Homeassistant server at home and I wanted my phone to send my location to it, but it was not possible when there is no direct connectivity. Solution - I needed direct connectivity from the internet to my router which port forwards to my server.

Instructions

Go to linode.com and order cheapest (shared CPU, 1 core, 1GB of RAM, 5$/month) instance with latest Rocky Linux. At the time of writing I used Rocky Linux 8.

Connect to the instance via SSH, root user and execute the following commands by literally copying & pasting them all into the terminal:

# Update system
dnf update -y --refresh

# Install additional repos
dnf install -y elrepo-release epel-release

# Install wireguard tools
dnf install -y kmod-wireguard wireguard-tools

# Stop & disable firewalld
systemctl disable --now firewalld.service

# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1	
sysctl -a | grep all.forwarding > /etc/sysctl.conf

# Generate wireguard keys
cd /etc/wireguard && wg genkey | (umask 0077 && tee server.key) | wg pubkey > server.pub
cd /etc/wireguard && wg genkey | (umask 0077 && tee client.key) | wg pubkey > client.pub

# Create wireguard server config file /etc/wireguard/wg0.conf
cat <<EOT > /etc/wireguard/wg0.conf
[Interface]
Address = 10.200.200.1/24
ListenPort = 51820
PrivateKey = $(</etc/wireguard/server.key)

PostUp = iptables -t nat -A PREROUTING -p tcp --dport 22 -j ACCEPT; iptables -t nat -A PREROUTING -p udp --dport 51820 -j ACCEPT; iptables -t nat -A PREROUTING -j DNAT --to-destination 10.200.200.2; iptables -t nat -A POSTROUTING -j MASQUERADE
PostDown = iptables -t nat -D PREROUTING -p tcp --dport 22 -j ACCEPT; iptables -t nat -D PREROUTING -p udp --dport 51820 -j ACCEPT; iptables -t nat -D PREROUTING -j DNAT --to-destination 10.200.200.2; iptables -t nat -D POSTROUTING -j MASQUERADE

# Mikrotik router
[Peer]
PublicKey = $(</etc/wireguard/client.pub)
AllowedIPs = 10.200.200.2/32
EOT

# Generate Mikrotik commands list by executing below multiline command
cat <<EOT > /etc/wireguard/mikrotik_commands.txt
# Create wireguard interface
/interface wireguard add listen-port=13235 mtu=1420 name=wg99 private-key="$(</etc/wireguard/client.key)"

# Connect to the wireguard server
/interface wireguard peers add allowed-address=10.200.200.0/24 endpoint-address=$(curl -sL https://ipv4.wtfismyip.com/text) endpoint-port=51820 interface=wg99 persistent-keepalive=25s public-key="$(</etc/wireguard/server.pub)"
	
# Set IP for wireguard interface
/ip address add address=10.200.200.2/24 interface=wg99 network=10.200.200.0

# Exclude such traffic from fasttrack/allow in firewall
/ip firewall filter add action=accept chain=forward in-interface=wg99 place-before=[find where action=fasttrack-connection]
/ip firewall filter add action=accept chain=forward out-interface=wg99 place-before=[find where action=fasttrack-connection]
EOT

# Enable wireguard server on boot
systemctl enable wg-quick@wg0.service

# Reboot the system
reboot

As you can see the last command reboots your instance. Reconnect to it and print the contents of file

/etc/wireguard/mikrotik_commands.txt

:

cat /etc/wireguard/mikrotik_commands.txt

This file contains all the generated commands you need to copy & paste (all at once) into your Mikrotik terminal and execute them.

Once done, you should have connectivity from Linode’s instance public IP address. Try port forwarding port in your Mikrotik router and checking port on your Linode’s instance IP - it should return what your router is supposed to return.

Note that the traffic is coming from wg99 interface, IP 10.200.200.1, so you might need to adjust your port forwarding rules accordingly.

Alternative, if Home Assistant is your only use-case, is just to use Nabu Casa / Home Assistant Cloud cloud service.
Slightly more expensive at 6.5USD/month but a much more simple setup, directly from your HA → SaaS platform.

2nd variant: …get a VPS (KVM) that allows to install your own image (mine is approx 3USD/month, 1vCPU, 2GB RAM, 20GB SSD, 40TB traffic - but anything with 512MB+ RAM will do fine) and host/install a Mikrotik CHR on it.

CHR costs money and if you want it free - you are limited to 1mbps only.

Zerotier?

Not all devices have access to zerotier.

Thank you. This is helpful. I just don’t know how to do the last part. Say I have the default configuration in the Mikrotik router (192.168.88.1 as the LAN address) and I followed the instructions to configure the Wireguard and peers in Mikrotik router, if I have to do the port forwarding in Mikrotik should I do this in Firewall?

General:
chain = dstnat
Dst. Address =

Action:
action = dst-nat
To Addresses = 192.168.88.1

Your solution is not free, too.
…running one year of your linode VPS is as expensive as my VPS (1 year) + one, onetime P1 CHR licence…at least in my calc sheet, just sayin’

How do I go about the fort forwarding in the Mikrotik router?

Ports are not specified anymore because it will be for all, is this correct?

General:
chain = dstnat
Dst. Address =

Action:
action = dst-nat
To Addresses = 192.168.88.1

…in this setup, there is no need for port-forwarding on the MT router.
MT router will enable the link to VPS via its wg enpoint-configuration in the peer to VPS, hence overcoming the CGNAT limitation of the local MT WAN-Link.
Once the tunnel is established, it will be fully bi-directional, even if opened from only from one side.

I think what was meant instead of “forwarding rules” is “adjust rules in the forward chain”, since traffic over wg-interface will be routed via 10.200.200.0/24 net and ip addresses attached to the wg-interface.


If your local MT has a standard firewall setup, i.e. like this: https://help.mikrotik.com/docs/display/ROS/Building+Advanced+Firewall
…just add the wg-interface to the LAN interface-list of the MT: /interface list member add interface=wg99 list=LAN

Thanks Hominidae! I was able to add the wg interface to the LAN list (and WAN list). Both or either of them works and I don’t know the difference but as of now, it is just in the LAN list.

The VPS shows that a peer is connected. The peer is my Mikrotik Router. I can now ping the 10.200.200.2 from VPS and I can ping 10.200.200.1 from any device in my local network. I was able to do the port forwarding in Mikrotik to forward all tcp and udp to a local server that has an IP address of 192.168.88.50. The port forwarding is working based on my test.

I am not an expert when it comes to networking but my understanding is, it has this direction now:

any public IP > public IP of the VPS > My Mikrotik > a local server

The local server still communicates to the internet but it uses the public IP of my mobile data network which is in CGNAT. I would like the local server to use the 10.200.200.1 network to communicate to the internet so that if I check its public IP, it will show the public IP of the VPS. Is this possible or is this part of the limitations in this kind of setup?

So far, this is what I did but the local server is unable to connect to the internet but the port forwarding is still working:
Table: I create a table called “wg”.
Firewall > Mangle: A mangle that has a “Src Address List” = LocalServerName (the IP address is declared on the Address List) is set to “Mark Routing” and uses the “wg” table name.
Route List: Gateway:10.200.200.1 and “Routing Table” = wg

OK, now I got it.
So the inbound traffic from VPS to your local net works. What is not working is that local host is not using VPS as gateway.

This is how I am doing this (I do this, in order for my VOIP-PBX to use the VPS as a constant WAN IP/GW, regardless of the actual IPs of my local, multiple WANs)

  • have/create a local IP on VPS (my VPS is running a MT CHR; I created a bridge and added address/IP 192.168.255.254/32 to it.
  • make sure that VPS has a valid default route and outbound NAT (when doing a ping from local interface/192.168.255.254 on VPS, it will use its own WAN interface and outbound Internet access works)
  • on local MT create a route to VPS-IP with gateway being the remote IP/VPS-side of wg-interface (you should be able to ping the VPS IP from your local net via wg-tunnel, hence).
  • on local MT create two address lists 1. all IPs of local hosts that should use VPS as WAN-gateway 2. all IPs that should not be routed to VPS, i.e. all your local networks
  • on local MT create a mangle rule in firewall: chain=prerouting, src-address-list = list#1, dst-address-list != list#2, action route, route-dst=192.168.255.254 (local IP of VPS) Edit: note do set dst-list not-equal-to list#2

…works like a charm for me

Hi Hominidae,

I was able to setup a Mikrotik CHR. It has just the default configuration. My understanding is this:

Mkrotik CHR (public IP) <------wireguard tunnel------> my local Mikrotik (CGNAT)

In configuring the wireguard of the local Mikrotik, I put the public IP of the Mikrotik CHR is the endpoint peer. How about in the Mikrotik CHR, what is the endpoint IP I should put?

Thanks!

Do I have to buy a CHR license or the free version is good?

…not needed.
The local MT will use the endpoint config to initiate the tunnel to the CHR. As it is behind CGNAT, the CHR can’t reach/connect to it anyway.
Once the tunnel is up, it will be bi-directional.
Keep an eye on the persistent keepalive setting in wg-peer …it should be smaller than the connection timeout in the firewall in order to prevent the conntrack to kick in and delete the connection in your NAT/conntrack table.
AFAIR my conntrack timeout for UDP connections is set to 2mins…I have my keepalive settings around 22-25secs.


For testing purposes, it will work. But the free License is limited to 1Mbps only. AFAIR, when you activate a test license (P1 = 1G) it will run for 30days and fallback to free (1M) afterwards.
So you have some time to test and evaluate. A CHR license is never lost but only bound to a single instance at a time. You can tear down your install and build another later, then transfer the license.

..and don’t forget to secure your CHR properly :wink:

Hi Hominidae,

I am still trying my best to accomplish my goal using the method you recommended which is to use a CHR. I have a question about the original post of “erkexzcx”. Let’s say his method works, that means that I am not limited to 1MBPS of speed only, is that correct?

Thanks!

…I am not recommending the use of a CHR, it is just what I do use.
You can of course do that with any VPS, running a linux OS and with iptables and wireguard installed.
But since you do have a MT and know your ways there, why introduce another system type?
A P1 license is not coming with a huge price tag, isn’t it?
I do own a couple of these and bought them for prices between 25-35USD over the years…worth every penny, if you ask me.

I think I followed the recommended settings based on the other post in the forum but it still doesn’t work.

Whenever I enable the routing rule, the device wouldn’t connect to the internet.

My goal is to be able to use the wireguard as gateway so that the public of the device with an IP address of 192.168.88.253 will become 172.104.48.54.

Pinging from VPS to 10.200.200.2 is good. Pinging the Mikrotik (and any devices connected to Mikrotik) to 10.200.200.1 is also good.




Here is the current configuration in the VPS:

[Interface]
Address = 10.200.200.1/24
ListenPort = 51820
PrivateKey = SPOZPusRrSlt+Tm3clLD164drtkcTtWRbZrI/E+oJFQ=

PostUp = iptables -t nat -A PREROUTING -p tcp --dport 22 -j ACCEPT; iptables -t nat -A PREROUTING -p udp --dport 51820 -j ACCEPT; iptables -t nat -A PREROUTING -j DNAT --to-destination 10.200.200.2; iptables -t nat -A POSTROUTING -j MASQUERADE
PostDown = iptables -t nat -D PREROUTING -p tcp --dport 22 -j ACCEPT; iptables -t nat -D PREROUTING -p udp --dport 51820 -j ACCEPT; iptables -t nat -D PREROUTING -j DNAT --to-destination 10.200.200.2; iptables -t nat -D POSTROUTING -j MASQUERADE

Mikrotik router

[Peer]
PublicKey = H1ENrFj2o7A2+BZUgDee2+N0qQRvxpTUML2mQs9agjU=
AllowedIPs = 10.200.200.2/32, 192.168.88.0/24

export.rsc (8.27 KB)

THis is how to get a public IP thread.
If you have a wireguard issue then post a NEW THREAD…

@aliboy: You have allowed-address=10.200.200.0/24, so nothing else will be allowed to pass. If you want it for traffic from internet, you need 0.0.0.0/0.