Having trouble setting up WireGuard

Hello!

The goal: set up a VPN tunnel and pass traffic to certain sites through it.

I’ve managed to do just that via ProtonVPN IPsec tunnel just a week ago. But, as of today, our government started to block connections to the popular VPN providers (HOO-RAH!). As a result, my IPsec tunnel doesn’t work anymore.

WireGuard still seems to work, though. I’ve managed to establish connection to the server via the Windows client. So now I’m trying to set the thing up on my router.

I’ve kinda figured a few things out, but I’m still very new to WireGuard and RoS 7 routing (and routing in general) so I’m struggling to make sense of what I have to do in order for things to start working. On top of that, some of the issues might be due to my ISP’s potential molestations of VPN connections.

Here are the pieces of the puzzle I’ve managed to put together:

/ip firewall
address-list add address=example.com list=PASS_THROUGH_VPN
mangle add action=mark-routing chain=prerouting dst-address-list=PASS_THROUGH_VPN new-routing-mark=through-vpn passthrough=yes

# WireGuard-related settings were taken from the ProtonVPN connection config
/interface wireguard 
add listen-port=13231 mtu=1420 name=proton-vpn private-key=omitted
peers add allowed-address=0.0.0.0/0 endpoint-address=omitted endpoint-port=51820 interface=proton-vpn persistent-keepalive=25s public-key=omitted

/routing 
table add disabled=no fib name=through-vpn
rule add action=lookup-only-in-table routing-mark=through-vpn table=through-vpn disabled=no

/ip 
address add address=10.2.0.2/24 interface=proton-vpn network=10.2.0.0 # The address is taken from the connection config
route add dst-address=10.2.0.0/24 gateway=proton-vpn routing-table=through-vpn
route add dst-address=0.0.0.0/0 gateway=proton-vpn routing-table=through-vpn

# I suppose I need something like this, but I'm not yet sure what address and port to use. The rule is currently disabled
/ip firewall filter add action=accept chain=input comment="accept: wireguard peer" connection-state=new disabled=yes log=yes protocol=udp src-address=??? src-port=???

To me, it seems like I should be almost there. Almost, but not quite, apparently. I can ping 10.2.0.1 from the router (which is a remote ProtonVPN DNS server located in the same subnet the interface is), but the sites from the address-list won’t open on the connected to the router devices. Where do I go from here? Not really sure how to start troubleshooting this. Any help would be greatly appreciated.

Thanks!

Router: hAP ac2
Firmware: RouterOS 7.2.3

You want this:

/ip firewall nat
add chain=srcnat out-interface=proton-vpn action=masquerade

And the first manual route to 10.2.0.0/24 is not needed.

Can you confirm if proton wireguard gave you a fixed Wireguard IP, or a subnet??

On local MT router how many subnets/vlans do you have.
Do you want all subnets to go out vpn for internet?
Do you want any subnet to reach local servers?
Do you want any users to reach local servers?

Hello! Thanks for the responses!

Going to reply in separate posts, the markup seems to get a bit messy.

Oh, good catch! Actually, I have a masquarade rule. And I even added proton-vpn interface to the WAN list. But, for some reason, I disabled the list entry with proton-vpn interface while tinkering around and then forgot to enable it back :slight_smile:

Here is the rule, just in case:

/ip firewall nat add action=masquerade chain=srcnat comment=masquerade out-interface-list=WAN

.

Right, 0.0.0.0/0 should catch 10.2.0.0/24. Removed.

After adding the proton-vpn interface entry back to the WAN list and removing the route, sites started to open. Yay! Thanks :slight_smile:

The load times aren’t that great for some reason, though (takes about 20 seconds to start loading a page). I suspect this might be due to some misconfiguration as the servers aren’t currently under heavy load (~60% at the moment). Going to try to switch the servers and see if it gets better.

That was my understanding. Here is what the interface part of the config looks like:


[Interface]
PrivateKey = omitted
Address = 10.2.0.2/32
DNS = 10.2.0.1

.

These seem like leading questions :slight_smile:

I have a few VLANs. Some VLANs have access to each other. Generally, VLANs should connect to the internet directly (without using the tunnel), but when they are trying to reach certain sites from the list, the traffic should be routed through VPN. This is done to access the sites blocked by the ISP. WireGuard tunnel shouldn’t interfere with the communication between subnets and local machines.

Do you have fasttrack rule in /ip/firewall/filter? That can slow things down, because it doesn’t go well together with mangle rules.

Glad you asked! I forgot I had a few quesions about fasttrack. I do have the rule, but I have altered it so it (presumably) wouldn’t process the marked traffic:

/ip firewall filter add action=fasttrack-connection chain=forward connection-state=established,related hw-offload=yes \
realm=!1024 \ # That must be what's shown in WinBox as routing-table=!through-vpn
routing-mark=!through-vpn

I don’t really know how fasttrack rule affects anything vpn-related, but, reading through the IPsec guide, I’ve read that it might mess things up. So first I removed the rule altogether, but then (after running a few BTests) I realized that performance without fasttrack isn’t really great. So I brought the rule back, but, this time, I excluded the marked traffic via connection-mark attribute in the fasttrack rule. Haven’t noticed any issues and the sites were opening quite fast.

Here, with WireGuard, I did a similar thing. But, of course, I had to switch from connection marking to route marking and, as you can see, I simply used two available rules without really knowing which one would work best (cover more ground, so to speak). I’d appreciate if you could elaborate which one I should use. Or maybe I should leave them both? Or, well, maybe I can’t have fasttrack at all with this kind of setup :slight_smile:

Thanks!

You need to mark connections and then mark routing based on connection mark. That’s because firewall rules apply to all packets in any direction. So even if you exclude outgoing packets based on routing mark, the same rule will still apply to any response to these connections that’s coming back. So something like:

/ip firewall mangle
add chain=prerouting connection-state=new dst-address-list=PASS_THROUGH_VPN action=mark-connection new-connection-mark=VPNconn passthrough=yes
add chain=prerouting in-interface-list=LAN connection-mark=VPNconn action=mark-routing new-routing-mark=through-vpn

And condition for fasttrack rule can be just connection-mark=no-mark.

Not sure I fully understand why just yet, but this seem to have sped the things up a great deal. It’s now impossible to tell if the traffic goes through VPN or not. I think some of the sites open even faster than on my regular connection!

I now only have one question left. Is there anything I should know security-wise when setting up a WireGuard tunnel? Some common pitfalls? My firewall is set up fairly tight - allow communication between certain interface/address lists, drop everything else - which seems to suffice, but I still can’t help but feel that I might be overlooking something.

Thank you!

If local 192.168.88.100 (or whatever you have) wanted to connect to 1.2.3.4 (which was listed in PASS_THROUGH_VPN), you marked routing for this packet and then routing-mark=!through-vpn in fasttrack rule made sure that fasttrack didn’t touch it. But then came first response packet from 1.2.3.4 to 192.168.88.100, it didn’t get any routing mark and fasttrack rule applied to it.

Now the connection gets marked with first request packet and if the packet is from LAN then it gets routing mark. But response packet is automatically recognized as part of connection and it gets connection mark. And fasttrack rule won’t touch it, because it takes only packets without connection mark.

As for firewall, keep it simple, allow what needs to be allowed and block the rest. Or in (many) more words: https://forum.mikrotik.com/viewtopic.php?t=180838

Post the complete config and I will have a look.
/export file=anynameyouwish

Ah, I see. That makes sense. I think I got it now. Thanks for the elaboration!


Yeah, I went down exactly this road. Monitoring and figuring what needs to go where as I go :slight_smile:


That’s very kind of you! The config is a bit cluttered with WLAN settings, DHCP-leases, static DNS records, and such. So I reformatted and trimmed it down for the ease of comprehension. The order of the commands might be screwed up, and there might be some typos, but I believe it would be easier to read it this way. Feel free not to if it’s still too much trouble, though. Going through the entire config feels like a bit too much to ask for.
config.rsc (8.43 KB)

(1) You lost me with this one.
/interface wireguard peers add allowed-address=“omitted” endpoint-address=“omitted”
endpoint-port=“omitted” interface=proton-vpn persistent-keepalive=25s public-key=“omitted”

That is critical to understand and ensure your setup is good and is not a security risk at all.
You are connecting to a third party VPN for internet so the setting would be 0.0.0.0/0 what is the big secret.??

(2) Missing IP pool, dhcp server, dhcp server network for vlan4000!!

(3) YOu can get rid of the bits of your firewall rule “connection-state=new” does nothing for you.

(4) BY adding the wireguard interface to the WAN interface, can I surmize that you have two purposes for this:
a. the purpose is that the firewall rule VLAN to WAN , includes such traffic to enter the tunnel (and later we use mangle rules to limit which destination addresses are permitted for these users).
add comment=“forward: accept access-to-internet list → wan”
chain=forward action=accept
in-interface-list=ACCESS_TO_INTERNET out-interface-list=WAN

b. to sourcenat all subnet users to the IP of the wireguard interface…

/ip firewall nat add chain=srcnat action=masquerade comment=masquerade out-interface-list=WAN

(5) What I dont understand is which subnets are supposed to use the Wireguard tunnel?
I get the feeling you want all users to use proton for internet…
From reading there are some websites for which you dont wan them to access or is it only a few websites they should be allowed to visit.

I am thinking there may be an easier way to do this…

Thanks for taking a look!


Ah, not a secret, really. It is 0.0.0.0/0. I was editing out Proton-specific configuration details, thought this one would be irrelevant too.


That was a deliberate choice. Don’t need them just yet :slight_smile:


Hm. The idea behind the rules was to be as specific as possible. Setting the rules this way should also cut out unwanted connection states like invalid and untracked. Have I missed something and these connection states can still leak?


That’s just a way of enabling masquerading on the WG interface. As you’ve mentioned, I am in fact connecting to a third-party VPN so having my internal network behind NAT seemed like a sensible thing to do security-wise at the time. Should I create a separate masquerade rule instead? I might very well be missing something and this doesn’t work as intended.

Now, currently, my biggest concern is if my firewall is tight enough that I won’t have to add rules like:

add action=drop chain=forward connection-nat-state=!dstnat connection-state=new in-interface-list=WAN

As a matter of fact, I do have this rule enabled, but just to monitor if there are any connections of this kind being made (none so far). I’m planning to remove it later on so I removed it from the posted configuration.


I’ve mentioned the general idea in this post. I am currently not limiting users from using WG tunnel, quite the opposite. I’ve set the thing up so they could access the sites from the list via the tunnel. Might narrow down the list of VLANs that have access to that later on, though — my VMs aren’t really supposed to visit blocked sites :smiley:

There is a centralized registry of the sites all our ISPs are obliged to block. If they don’t, they might get fined or worse, so they comply. Some of the finest examples of currently blocked sites are: all independent news sources, facebook, instagram, twitter. So we have to use VPN to read news and browse tanned butts. But that’s about it, the rest shouldn’t go through VPN. Blocked sites → WG, rest → normal routing path. Note the mangle rules which only mark connection to sites from the list to be routed through VPN.


Edit:
I just realized that the unused ACCESS_TO_BLOCKED_SITES list might’ve steered you off. The VLAN structure, inter-VLAN access and such are currently under development so the inside-network-config part isn’t final yet. I.e. clients accessing something isn’t much of a concern atm. The concern is someone outside accessing the clients through a scary tunnel :slight_smile: The connection marking rule was supposed to look like this:

add action=mark-connection chain=prerouting new-connection-mark=pass-through-vpn \
    in-interface-list=ACCESS_TO_BLOCKED_SITES \
    dst-address-list=PASS_THROUGH_VPN \
    connection-state=new passthrough=yes

Then this works…
add action=mark-connection chain=prerouting new-connection-mark=pass-through-vpn
in-interface-list=ACCESS-TO-BLOCKED_SITES
dst-address-list=PASS_THROUGH_VPN
connection-state=new passthrough=yes

+
add action=mark-routing chain=prerouting new-routing-mark=through-vpn
dst-address-list=!VLAN-Subnets
connection-state=new passthough=yes

Hint: You have to make a firewall address list of the VLAN subnets…
In this manner you dont mark the return traffic and it gets routed properly back to the subnets and not back out the tunnel again.


Alternatively you could have
add action=mark-routing chain=prerouting new-routing-mark=through-vpn
in-interface-list=VLAN
connection-state=new passthough=yes

and the mark routing will match only on the outgoing traffic and not on the return traffic.

Not the blue one. First, it’s not needed, because connection mark is assigned automatically by conntrack. And second, it’s wrong, you can’t use out-interface-list in prerouting. And when marking routing, you want it only for outgoing traffic.

Edit: I don’t like people who edit their posts too much. :wink:

Oh gawd. I’ve already written a response for anav elaborating why the suggested line shouldn’t work, was about to post, and the message is already gone :smiley:

Anyway, I think I’ll leave my understanding of how this works here to help others avoid a pitfall I’ve already managed to step in :slight_smile:

Right now the combination of rules works as follows.

  1. Router sees a connection from a local machine to an address from the list, the mangle rule marks this connection
  2. Router sees the marked connection and modifies the routing mark so the destination would be looked up in another routing table
  3. The http request goes through the route from through-vpn table
  4. The http response comes back and gets returned to the sender

If you’re to deliberately mark the http response too (or to merely forget to specify that only LAN->WAN should be marked), it would get marked with the route mark too, and their destination is going to be looked up in the table which only has a wireguard gateway (through-vpn table). Which in return is going to cause an explosion.

That’s my understanding which isn’t to be relied upon :smiley: Feel free to correct me if I’m wrong.

PS: I’ve made an isolated, default-configuration-oriented script for those willing to implement a similar setup (already partially tested on my human-friend-test-subject!). Going to post it soon if I’ll find no issues with it.

Sob check my post above your post. I went back in time and changed the world.

You have the power to go back in time and change the world, and you waste it on changing forum posts? And the change is still wrong. :wink: I mean the first one, there’s srcnat, so responses in prerouting won’t have any LAN address as destination, it will be whatever srcnat used as new source. The other one is fine.