VPN subnet for wifi clients

Hello!

I have a mikrotik router RB951G-2HnD.
I’ve started from the default config.
I’ve added a wireguard tunnel to my remote server, it works (I see pings on the other side).
Now I want all wifi traffic go inside the tunnel, and all wifi clients have addresses from vpn range 172.16.1.0/24 (but keep my wired LAN in its default range 192.168.88.1/24).
My plan is:

  1. add a new bridge, say wg-bridge, take wlan1 out of default “bridge” and add it to wg-bridge.
  2. add a new dhcp-server, say wg-dhcp
  3. add a new /ip/pool 172.16.1.0/24, attach it to wg-dhcp
  4. add vpn subnet to /ip/dhcp-server/network

Will it work? Is there a simpler way? I want to understand how everything works, so please comment on the plan rather than providing a ready config.

Note, that I don’t want to do masquarade on Mikrotik. Say wifi client got ip 172.16.1.5, then it sends a packed to some host on the internet, say 5.6.7.8, the packet should go to mikrotik, then into the tunnel to vpn gateway 172.16.0.1, there it will be subjected to masquarade and sent into internet. Wifi clients also should freely talk to any host inside vpn, say 172.16.0.33. Here’s the picture:

[Wifi Client 172.16.1.5]
             v
         (wifi, wpa2)
             v
[Mikrotik LAN=192.168.88.1/24 wg=172.16.1.1]
             v
  (wireguard, UDP through internet)
             v
[remote WG Gateway server 172.16.0.1] --(wireguard to another peer)--> [172.16.0.33]
             v
     (HTTP over internet)
             v
[some host 5.6.7.8 on internet]

v and > show direction of traffic, () mark traffic type and medium, mark hosts

My router is a common home router with 5 ethernet ports and wifi. The default config is such that port ether1 is ISP uplink, and ports ether2-5 and wlan1 are joined into bridge “bridge”. Firmware:

[admin@MikroTik] /system/routerboard/print
routerboard: yes
model: RB951G-2HnD
firmware-type: ar9344
factory-firmware: 3.02
current-firmware: 7.13
upgrade-firmware: 7.13

Create a new bridge and name it something recognisable, like “Guest-Bridge.” Then go to IP > Address and assign an IP address to this bridge so it’s on a different subnet than your main network, for example, 172.16.1.1/24. Next, create a virtual WLAN for guest WiFi. Go to Bridge and assign this WLAN to the Guest-Bridge.

After that, go to IP > DHCP > DHCP Setup, specify the Guest-Bridge interface, and most of the information should be filled in automatically - just modify any settings if needed. Once your guest WiFi is set up, go to Routing > create a new routing table, and name it, for example, “VPN.” Tick the “fib” box.

Then go to Routing > Rules, specify the source address, which in this example would be your guest WiFi subnet (172.16.1.1/24), set the action to “lookup only in table,” and for the table select “VPN”. Finally, go to IP > Routes > add a new route with the destination address 0.0.0.0/0, set the gateway to your VPN gateway, and choose the VPN routing table.

If anyone notices any mistakes in my instructions, please correct me, but as far as I’m aware, this should work. Obviously, to communicate between these networks via the VPN, you’ll need to create routes on the other side of the tunnel too.

Thanks, it worked with one minor addition. I’ll post my config just in case.

The common VPN protocols going outside the country are currently being blocked in Russia. Shadowsocks works though. Because I can’t maintain shadowsocks link for every site I need VPNed I decided upon the following setup. For the common use case there are 4 devices involved:

  • R: remote (Dutch) server used as a VPN exit node when DPI must be circumvented, debian linux 11, 172.16.0.1, has public static ip


  • H: a ‘hub’ server, has shadowsocks tunnel to R, also debian linux 11, 172.16.0.17, has public static ip


  • M: on-site mikrotik, connected to H by ordinary wireguard, 172.16.0.25


  • C: wifi client to M, laptop, tv, etc, 172.16.1.0/24

In-country wireguard traffic isn’t being blocked (at least by my ISPs), thus M and H can talk over plain wireguard. H and R can’t use wireguard directly, the connection is being disrupted. So I connect them with wireguard over shadowsocks which is somewhat inefficient, but works. All in angle brackets must be replaced with appropriate values for configs to work.

R wireguard config

/etc/wireguard/wg16.conf:

        [Interface]
	Address = 172.16.0.1/16
	PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
	PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
	ListenPort = <R-wg-port>
	PrivateKey = <R-priv-key>

	#...

	[Peer]
	PublicKey = <H-pub-key>
	AllowedIPs = 172.16.0.17/16

to enable in systemd:

sudo systemctl enable --now wg-quick@wg16

R shadowsocks config (server)

/etc/shadowsocks-libev/config.json:

	{
		"server":"0.0.0.0",
		"mode":"tcp_and_udp",
		"server_port":<R-ss-port>,
		"password":"<ss-password>",
		"timeout":300,
		"method":"chacha20-ietf-poly1305"
	}

to enable in systemd:

sudo systemctl enable --now shadowsocks-libev.service

H wireguard config

/etc/wireguard/wg16.conf:

	[Interface]
	PrivateKey = <H-priv-key>
	Address = 172.16.0.17/16
	ListenPort = <H-wg-port>
	PostUp   = iptables -A FORWARD -i wg16 -j ACCEPT; ip6tables -A FORWARD -i wg16 -j ACCEPT
	PostDown = iptables -D FORWARD -i wg16 -j ACCEPT; ip6tables -D FORWARD -i wg16 -j ACCEPT
	
	# This is needed to avoid encryping shadowsocks with wireguard,
	# because wireguard needs to go over shadowsocks to reach R
	# 	<H-LAN-gateway> - e.g. 192.168.0.1
	PostUp   = ip route add <R-public-ip>/32 via <H-LAN-gateway> dev eth0
	PostDown = ip route del <R-public-ip>/32 via <H-LAN-gateway> dev eth0

	# ... some other peers connect directly to H, not through M

	[Peer]
	# connection to R over shadowsock
	PublicKey = <R-pub-key>
	Endpoint = 127.0.0.1:<H2R-tunnel-port>
	PersistentKeepalive = 15
	AllowedIPs = 0.0.0.0/0
	
	[Peer]
	# connection from M
	PublicKey = <M-pub-key>
	AllowedIPs = 172.16.0.25/32, 172.16.1.1/24

to enable in systemd:

sudo systemctl enable --now wg-quick@wg16

H shadowsocks config (client)

/etc/shadowsocks-libev/hub.json:

	{
	 "server": "<R-public-ip>",
	 "mode":"tcp_and_udp",
	 "server_port":<R-ss-port>,
	 "local_address": "127.0.0.1",
	 "local_port":<H2R-tunnel-port>,
	 "password":"<ss-password>",
	 "timeout":300,
	 "method":"chacha20-ietf-poly1305",
	 "tunnel_address": "127.0.0.1:<R-wg-port>"
	}

to enable in systemd:

sudo systemctl enable --now shadowsocks-libev-tunnel@hub.service

M config

Start with the default config, then:

# add wireguard
/interface/wireguard/add name=wg listen-port=<M-wg-port> private-key="<M-priv-key>"
/interface/wireguard/peers/add allowed-address=0.0.0.0/0 endpoint-address=<H-public-ip> endpoint-port=<H-wg-port> interface=wg public-key="<H-pub-key>" comment=H
/ip address add address=172.16.0.25/16 interface=wg

# add bridge-wifi, move wlan1 to it
/interface/bridge/add name="bridge-wifi"
/ip/address/add address=172.16.1.1/24 interface=bridge-wifi
/interface/bridge/port/set [ find interface=wlan1 ] bridge=bridge-wifi
/ip/pool/add name=wifi-dhcp ranges=172.16.1.2-172.16.1.254
/ip/dhcp-server/add interface=bridge-wifi address-pool=wifi-dhcp name=wificonf

# routing
/routing/table/add name=rtvpn fib
/routing/rule/add src-address=172.16.1.1/24 action=lookup-only-in-table table=rtvpn
/ip/route/add dst-address=0.0.0.0/0 gateway=wg routing-table=rtvpn 

# I had to add this to your instructions, somehow it works
/ip/dhcp-server/network/add address=172.16.1.0/24 gateway=172.16.1.1 dns-server=8.8.8.8