Stuck getting VPN tunneling traffic routed

I think I’ve hit a brick wall. I have my VPN client setup and connected successfully. My provider is Private Internet Access. The problem I’m having is I cannot get my laptop to connect to the internet via the VPN tunnel. I configured a split-tunnel with my Primary LAN on 192.168.0.0/22.

Note: This is a new router and hasn’t been fully deployed yet. It’s currently connected to my production router (Ubiquiti Edge Router Pro) which is acting as the WAN gateway (subnet: 192.168.10.0/24) until I can get everything setup on this Mikrotik (Cloud Core Router).

I have a VPN Address list called: VPN_Addresses
I setup the mangle rules, NAT, and firewall rules and have debugged all of them without any success. I tried allowing all traffic through the firewall and didn’t see any improvements.
I’ve run the following commands on my laptop:
ping 8.8.8.8 - timeouts
traceroute google.com - I get only to the router hop 192.168.0.1
nslookup google.com - timeout

Please let me know if I’m missing some details to provide on my configuration.

ovpn client settings:

DHCP-Server info (Note: please ignore the DNS settings for m Guest and Management LAN those are set to my eventual internal DNS server - which isn’t acessible yet):

Flags: D - dynamic 
 0   ;;; Primary LAN DHCP Network Config
     address=192.168.0.0/22 gateway=192.168.0.1 dns-server=8.8.8.8,8.8.4.4 wins-server="" ntp-server="" caps-manager="" domain="local" dhcp-option="" 

 1   ;;; Guest LAN DHCP Network Config
     address=192.168.5.0/24 gateway=192.168.5.1 dns-server=192.168.1.97 wins-server="" ntp-server="" caps-manager="" dhcp-option="" 

 2   ;;; Management LAN DHCP Network Config
     address=192.168.99.0/24 gateway=192.168.99.1 dns-server=192.168.1.97 wins-server="" ntp-server="" caps-manager="" dhcp-option="" 

Ovpn status:

            ;;; OpenVPN Client for Split Tunnel
         status: connected                      
         uptime: 2m5s                           
       encoding: AES-128-CBC/SHA1               
            mtu: 1500                           
  local-address: 10.25.112.53  

This is the output of my ovpn-client:

Flags: X - disabled; R - running; H - hw-crypto; Ta - tls-auth; Tc - tls-crypt 
 0  RH     ;;; OpenVPN Client for Split Tunnel
           name="ovpn-pia" mac-address=02:D5:B2:93:AE:54 max-mtu=1500 connect-to=us-california.privacy.network port=1198 mode=ip protocol=udp user="XXXX" password="XXXX" 
           profile=pia-ovpn-profile certificate=none verify-server-certificate=yes tls-version=only-1.2 auth=sha1 cipher=aes128-cbc use-peer-dns=no add-default-route=no route-nopull=yes 
           disconnect-notify=yes 

A list of my routes:

Flags: D - dynamic; X - disabled, I - inactive, A - active; c - connect, s - static, r - rip, b - bgp, o - ospf, i - is-is, d - dhcp, v - vpn, m - modem, y - bgp-mpls-vpn; H - hw-offloaded; 
+ - ecmp 
   DAd   dst-address=0.0.0.0/0 routing-table=main gateway=192.168.10.1 immediate-gw=192.168.10.1%sfp28-1 check-gateway=ping distance=1 scope=30 target-scope=10 vrf-interface=sfp28-1 

   DAc   dst-address=10.2.112.0/24 routing-table=main gateway=ovpn-pia immediate-gw=ovpn-pia distance=0 scope=10 target-scope=5 local-address=10.2.112.151%ovpn-pia 

   DAc   dst-address=192.168.0.0/22 routing-table=main gateway=VLAN1-PrimaryLAN immediate-gw=VLAN1-PrimaryLAN distance=0 scope=10 target-scope=5 local-address=192.168.0.1%VLAN1-PrimaryLAN 

   DAc   dst-address=192.168.5.0/24 routing-table=main gateway=VLAN5-Guest immediate-gw=VLAN5-Guest distance=0 scope=10 target-scope=5 local-address=192.168.5.1%VLAN5-Guest 

   DAc   dst-address=192.168.10.0/24 routing-table=main gateway=sfp28-1 immediate-gw=sfp28-1 distance=0 scope=10 target-scope=5 local-address=192.168.10.10%sfp28-1 

   DAc   dst-address=192.168.99.0/24 routing-table=main gateway=VLAN99-Mgmt immediate-gw=VLAN99-Mgmt distance=0 scope=10 target-scope=5 local-address=192.168.99.1%VLAN99-Mgmt 

 0  As   ;;; Default route for VPN-marked traffic in custom table
         dst-address=0.0.0.0/0 routing-table=vpn-routing-table gateway=ovpn-pia immediate-gw=ovpn-pia distance=1 scope=30 target-scope=10 

My mangle rules:

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; Mark connections from VPN_Addresses for VPN
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes src-address-list=VPN_Addresses log=no log-prefix="" 

 1    ;;; Mark packets of VPN connections for VPN routing
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=yes connection-mark=vpn-connection 

 2    ;;; Mark TCP connections to VPN_Ports for VPN
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes protocol=tcp dst-port=16881,6881-6999 

 3    ;;; Mark UDP connections to VPN_Ports for VPN
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes protocol=udp dst-port=16881,6881-6999 

My NAT rules:

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; NAT for Primary Internet Access
      chain=srcnat action=masquerade routing-mark=!vpn-routing-table out-interface=sfp28-1 

 1    ;;; NAT for Secondary Internet Access
      chain=srcnat action=masquerade routing-mark=!vpn-routing-table out-interface=sfp28-2 

 2    ;;; NAT for VPN traffic
      chain=srcnat action=masquerade out-interface=ovpn-pia 

My DNS settings:

                      servers: 8.8.8.8
                               8.8.4.4
              dynamic-servers: 8.8.8.8
               use-doh-server:        
              verify-doh-cert: no     
   doh-max-server-connections: 5      
   doh-max-concurrent-queries: 50     
                  doh-timeout: 5s     
        allow-remote-requests: yes    
          max-udp-packet-size: 4096   
         query-server-timeout: 2s     
          query-total-timeout: 10s    
       max-concurrent-queries: 100    
  max-concurrent-tcp-sessions: 20     
                   cache-size: 2048KiB
                cache-max-ttl: 1w     
      address-list-extra-time: 0s     
                          vrf: main   
           mdns-repeat-ifaces:        
                   cache-used: 450KiB 

All my firewall rules attached
firewall-list.txt (29.0 KB)

You need to be more careful with your mark-routing rule.
It needs to be only done if the input interface is !=ovpn-pia, or it will route incoming stuff straight back out.
Likely also need to ensure destination ip is not one of the routers ip addresses, or other local lan addresses.

I would often force it to use routing rules (by not having the used routing mark in the route table) and use routing rules for both parts.

  1. force use of routing rule for marked packets.

    chain=prerouting action=mark-routing new-routing-mark=rule-vpn-routing-table passthrough=yes connection-mark=vpn-connection

/routing rule
add action=lookup comment=“min-prefix=0, all except 0.0.0.0/0 (so only all local stuff)” disabled=no min-prefix=0 table=main
add action=lookup disabled=no dst-address=0.0.0.0/0 routing-mark=rule-vpn-routing-table table=vpn-routing-table

** Note: the first routing rule simplifies things a lot but can apparently be flakey if you have changing routing tables **

Thanks @rplant I tried adding the !=ovpn-pia as the in interface and tweaked my rules, but I’m still not getting anything on traceroute or nslookup.

This is my current config:

Mangle rules:

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; Mark traffic from VPN_Addresses
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=yes src-address-list=VPN_Addresses in-interface=!ovpn-pia 

 1    ;;; Mark TCP traffic for VPN
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=yes protocol=tcp in-interface=!ovpn-pia dst-port=16881,6881-6999 

 2    ;;; Mark UDP traffic for VPN
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=yes protocol=udp in-interface=!ovpn-pia dst-port=16881,6881-6999 

NAT rules:

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; NAT for Primary Internet Access
      chain=srcnat action=masquerade routing-mark=!vpn-routing-table out-interface=sfp28-1 

 1    ;;; NAT for Secondary Internet Access
      chain=srcnat action=masquerade routing-mark=!vpn-routing-table out-interface=sfp28-2 

 2    ;;; Masquerade traffic for VPN
      chain=srcnat action=masquerade out-interface=ovpn-pia 

Route:

Flags: D - DYNAMIC; A - ACTIVE; c - CONNECT, s - STATIC, d - DHCP
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
#     DST-ADDRESS      GATEWAY           ROUTING-TABLE      DISTANCE
  DAd 0.0.0.0/0        192.168.10.1      main                      1
  DAc 10.24.112.0/24   ovpn-pia          main                      0
  DAc 192.168.0.0/22   VLAN1-PrimaryLAN  main                      0
  DAc 192.168.5.0/24   VLAN5-Guest       main                      0
  DAc 192.168.10.0/24  sfp28-1           main                      0
  DAc 192.168.99.0/24  VLAN99-Mgmt       main                      0
;;; Default route for VPN-marked traffic in custom table
0  As 0.0.0.0/0        ovpn-pia          vpn-routing-table         1

Any other suggestions?

Thanks!

Additional note. I tried a ping directly on the router and also am getting a timeout:

[admin@Mikrotik-Router] > ping 8.8.8.8 interface=ovpn-pia 
  SEQ HOST                                     SIZE TTL TIME       STATUS                                                                                                          
    0 8.8.8.8                                                      timeout                                                                                                         
    1 8.8.8.8                                                      timeout                                                                                                         
    2 8.8.8.8                                                      timeout                                                                                                         
    sent=3 received=0 packet-loss=100% 

Can you ping the vpn provider remote tunnelled ip (in the range 10.2.112.0/24)

Nope. No luck. :frowning: :pensive_face:

I’m also not seeting a “Remote Address” in the ovpn client.

Update. I can do a ping on the router to 8.8.8.8 via the src-address assigned by PIA.

It appears that PIA expects compression to be enabled, which the mikrotik won't do.
My guess is the connection might be up but is broken.
And also the ping is likely going via the main wan interface.
(You could try an /ip traceroute.)

Mikrotik uses a self-written reimplementation. Therefore it's not fully compatible with the official one - some features are not available.

Whether this is enough for you in your given circumstances is only known to you.

You can ask for features to be added or you can use wireguard; the implementation there is fully standard.

Just so you're aware: openvpn has lots and lots of features, and it would be a really huge undertaking to support all of them.

Well that's a real bummer. Appreciate the insights that certainly explains a lot. I just switched over to using wireguard and the following script to grab the PIA settings and setup the interface:

I believe the wireguard interface is now up and running but I'm still running into issues getting my laptop to connect out of the tunnel to the internet. I'm working through the different settings now to see where the issue is.

Glad to help, even if only somewhat.

Any problem you have will probably be resolved with tcp mss clamping.

I'm still stuck, unfortunately. I bypassed my split tunnel and sent all my packets our the VPN and I can confirm success connecting to the internet via the tunnel. So I'm not sure what's causing the issue with my split tunnel.

I tried pairing down to a very simple firewall setup to eliminate it and still no luck.

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; Allow established/related forward traffic
      chain=forward action=accept connection-state=established,related 

 1    ;;; VPN: Allow all NEW traffic destined for VPN
      chain=forward action=accept connection-state=new routing-mark=vpn-routing-table 

 2    ;;; VPN Kill Switch
      chain=forward action=drop routing-mark=vpn-routing-table out-interface=!wg-pia 

 3    ;;; Default Drop All Forward Traffic
      chain=forward action=drop 

My current active NAT and Mangle rules:

Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; NAT for Primary Internet Access
      chain=srcnat action=masquerade out-interface=sfp28-1 log=no log-prefix="" 

 1    ;;; NAT for Secondary Internet Access
      chain=srcnat action=masquerade out-interface=sfp28-2 log=no log-prefix="" 

 3    ;;; PIA VPN: Masquerade outgoing traffic
      chain=srcnat action=masquerade out-interface=wg-pia log=no log-prefix="" 


Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; Mark connections from VPN_Addresses
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes src-address-list="" dst-address-list=VPN_Addresses connection-mark=no-mark 
      log=no log-prefix="VPN-CONN" 

 1    ;;; Mark traffic from VPN_Addresses
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=no connection-mark=vpn-connection log=no log-prefix="VPN-ROUTE" 

probably should have src-address-list=VPN_Addresses rather than dst-address.

The Drop all forward traffic rule may be handy in the short term but probably needs to be removed eventually.

I assume you have a route in your route table with routing-table=vpn-routing-table pointing at wireguard1 (or whatever your wireguard inteface is called) something like:

/ip route
add comment=wg disabled=no dst-address=0.0.0.0/0 gateway=wireguard1 routing-table=vpn-routing-table

Though having said that, your route marking needs to be more restrictive again.
I would force use of routing rules instead they usually are more flexible.
Another option might be to copy and add all your lan network routes to the vpn-routing-table table.

Thanks @rplant. Your suggestions got me over the finish line!

I do have a routing rule.

;; Default route for VPN-marked traffic in custom table
         dst-address=0.0.0.0/0 routing-table=vpn-routing-table gateway=wg-pia immediate-gw=wg-pia distance=1 scope=30 target-scope=10 suppress-hw-offload=no

What seemed to solve it was adding a static route to my LAN network to route traffic to the vpn-routing-table.

;;; LAN: Ensure local traffic bypasses the VPN tunnel
         dst-address=192.168.0.0/22 routing-table=vpn-routing-table gateway=VLAN1-PrimaryLAN immediate-gw=VLAN1-PrimaryLAN distance=1 scope=30 target-scope=10 
         suppress-hw-offload=no 

I guess the core issue was that there appeared to be a routing conflict where my VPN-marked traffic was incorrectly trying to access local resources via the VPN tunnel (according to Gemini).

As an alternative, I tried adding a dst-address-list=!LAN_Networks to the mangle rules (I did change the address list from dst-address-list back to src-address-list). Below are my final mangle rules without dst-address-list=!LAN_Networks

0    ;;; Mark connections from VPN_Addresses
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes src-address-list=VPN_Addresses log=no log-prefix="" 

 1    ;;; Mark traffic from VPN_Addresses
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=no connection-mark=vpn-connection log=no log-prefix="" 

I first tried adding it to rule 0, then tried adding it to rule 1. Neither worked. Not sure why.

What would you recommend to make my marking more restrictive? or having the two rules like I originally had is what you were referring to?

Also I looked at trying to do routing rules instead of marking and couldn't find a way to do it in RouterOS 7 (I'm sure I missed something).

As for the Drop all forward traffic rule - why do you recommend removing it? Attached is my full firewall list. I tend to keep my LAN-WAN traffic restrictive so I can manage what devices send out of my network a bit better.
firewall-filter-rules.txt (28.9 KB)

Thanks again for your help!

Hi,
Your firewall rule list is way more complicated than I expected, I can only make the following suggestions for it.

Normally I would put all the input rules next to each other, also the forward rules, and output rules. (Though I guess grouping by function has some merit)

There is also the raw table, which I think would be a much more efficient place to put blanket ban lists, like "Block Blacklisted Inbound" though you will not know which interface the traffic is likely to leave through. (does this matter?)

Routing rules:

This is not a routing rule, it is a normal route just not using the default main routing table.

;; Default route for VPN-marked traffic in custom table
         dst-address=0.0.0.0/0 routing-table=vpn-routing-table gateway=wg-pi

Broadly to get routing marked packets to go through the routing rule table, the routing mark cannot exist in the routing table. The routing rule table is processed in order.

Something like

/routing rule
add action=lookup dst-address=192.168.0.0/22 table=main
add action=lookup routing-mark=rule-via-vpn table=vpn-routing-table

And the mangle rules would then use: new-routing-mark=rule-via-vpn rather than directly using vpn-routing-table.

Please correct me if I'm wrong, but it seems like RouterOS 7 won't allow us to use a routing-mark that isn't the routing table. I try commands to change the routing mark and it doesn't find it and if I go into the UI for the Mangle rules the only options that are listed are the Main Table and the VPN table I have already.

Yes, the routing mark used for the rules does need to be in / routing table
it also needs to be in fib (I am not sure why it needs to be in the fib)

Yep. A bit more on this:

FIB is needed, because you actually want to forward traffic according to your table.

Thanks for the clarification guys. Appreciate it. So what I currently have configured works but I suspect there's probably a better, more accepted way to do the split-tunnel. Can you guys please help me "gut check" my configuration? And if I need to make changes, please help clarify what and where?

Notes about the configurations below:

  • I have an alternate NAT rule (disabled currently) that is more strict for VPN traffic "Strict NAT for VPN-routed traffic" - do you think I should use that one instead of the one I am currently using?
  • The change in my config that got the split-tunnel to work was to add an IP Route for LAN/local traffic to bypass the VPN tunnel - "LAN: Ensure local traffic bypasses the VPN tunnel"

(Let me know if you need me to post my firewall rules again)
Thanks again for your help!

Mangle Rules:
lags: X - disabled, I - invalid; D - dynamic 
 0    ;;; Mark connections from VPN_Addresses
      chain=prerouting action=mark-connection new-connection-mark=vpn-connection passthrough=yes src-address-list=VPN_Addresses log=no log-prefix="" 

 1    ;;; Mark traffic from VPN_Addresses
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=no connection-mark=vpn-connection log=no log-prefix="" 

 2    ;;; Mark TCP traffic for VPN
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=no protocol=tcp connection-mark=!vpn-connection in-interface=!wg-pia 
      dst-port=16881,6881-6999 log=no log-prefix="" 

 3    ;;; Mark UDP traffic for VPN
      chain=prerouting action=mark-routing new-routing-mark=vpn-routing-table passthrough=no protocol=udp connection-mark=!vpn-connection in-interface=!wg-pia 
      dst-port=16881,6881-6999 log=no log-prefix="" 

 4    ;;; Mark routing for locally generated VPN traffic
      chain=output action=mark-routing new-routing-mark=vpn-routing-table passthrough=no connection-mark=vpn-connection 

NAT Rules:
Flags: X - disabled, I - invalid; D - dynamic 
 0    ;;; PIA VPN: Masquerade outgoing traffic
      chain=srcnat action=masquerade out-interface=wg-pia log=no log-prefix="" 

 1    ;;; NAT for Primary Internet Access
      chain=srcnat action=masquerade out-interface=sfp28-1 log=no log-prefix="" 

 2    ;;; NAT for Secondary Internet Access
      chain=srcnat action=masquerade out-interface=sfp28-2 log=no log-prefix="" 

 3 X  ;;; Strict NAT for VPN-routed traffic
      chain=srcnat action=masquerade routing-mark=vpn-routing-table out-interface=wg-pia log=no log-prefix="" 
      
Routing Rule:
Flags: X - disabled, I - inactive 
 0   ;;; Policy: Direct VPN-marked traffic to VPN routing table
     routing-mark=vpn-routing-table action=lookup-only-in-table table=vpn-routing-table 
     
IP Routes:
Flags: D - dynamic; X - disabled, I - inactive, A - active; 
c - connect, s - static, r - rip, b - bgp, o - ospf, i - is-is, d - dhcp, v - vpn, m - modem, y - bgp-mpls-vpn; H - hw-offloaded; + - ecmp 
   D d   dst-address=0.0.0.0/0 routing-table=main gateway=192.168.20.1 immediate-gw=192.168.20.1%sfp28-2 check-gateway=ping distance=10 scope=30 target-scope=10 
         vrf-interface=sfp28-2 

   DAd   dst-address=0.0.0.0/0 routing-table=main gateway=192.168.10.1 immediate-gw=192.168.10.1%sfp28-1 check-gateway=ping distance=1 scope=30 target-scope=10 
         vrf-interface=sfp28-1 

   DAc   dst-address=10.2.128.1/32 routing-table=main gateway=wg-pia immediate-gw=wg-pia distance=0 scope=10 target-scope=5 local-address=10.2.249.185%wg-pia 

   DAc   dst-address=192.168.0.0/22 routing-table=main gateway=VLAN1-PrimaryLAN immediate-gw=VLAN1-PrimaryLAN distance=0 scope=10 target-scope=5 
         local-address=192.168.0.1%VLAN1-PrimaryLAN 

   DAc   dst-address=192.168.5.0/24 routing-table=main gateway=VLAN5-Guest immediate-gw=VLAN5-Guest distance=0 scope=10 target-scope=5 
         local-address=192.168.5.1%VLAN5-Guest 

   DAc   dst-address=192.168.10.0/24 routing-table=main gateway=sfp28-1 immediate-gw=sfp28-1 distance=0 scope=10 target-scope=5 local-address=192.168.10.10%sfp28-1 

   DAc   dst-address=192.168.20.0/24 routing-table=main gateway=sfp28-2 immediate-gw=sfp28-2 distance=0 scope=10 target-scope=5 local-address=192.168.20.10%sfp28-2 

   DAc   dst-address=192.168.99.0/24 routing-table=main gateway=VLAN99-Mgmt immediate-gw=VLAN99-Mgmt distance=0 scope=10 target-scope=5 
         local-address=192.168.99.1%VLAN99-Mgmt 

 0  As   ;;; Default route for VPN-marked traffic in custom table
         dst-address=0.0.0.0/0 routing-table=vpn-routing-table gateway=wg-pia immediate-gw=wg-pia distance=1 scope=30 target-scope=10 suppress-hw-offload=no 

 1  As   ;;; LAN: Ensure local traffic bypasses the VPN tunnel
         dst-address=192.168.0.0/22 routing-table=vpn-routing-table gateway=VLAN1-PrimaryLAN immediate-gw=VLAN1-PrimaryLAN distance=1 scope=30 target-scope=10 
         suppress-hw-offload=no 
         
IP Tables:
Flags: D - dynamic; X - disabled, I - invalid; U - used 
 0 D   name="main" fib 

 1     ;;; Custom routing table for VPN traffic
       name="vpn-routing-table" fib