Solved Routing OpenVPN client as default gateway

I currently have a router using OpenVPN in client mode to connect to a host for anonymous internet access. I want everyone connected to the router to access the internet through OpenVPN. Is it possible to make OpenVPN the default gateway for everyone connected to the router without the clients needing to run openvpn themselves? If so assistance on this would be most appreciated.

This is my openvpn.conf:
Code:
setenv FORWARD_COMPATIBLE 1
setenv UV_SERVERID 183
client
dev tun
proto udp
remote 207.126.95.3 8292
nobind
persist-key
persist-tun
ns-cert-type server
key-direction 1
push-peer-info
comp-lzo
explicit-exit-notify
verb 3
mute 20
reneg-sec 86400
mute-replay-warnings
max-routes 1000

I removed the CA, cert, key and tls-auth from the file.
 
Hello,

I wrote a blog article about that point precisely. Check at step 9 (firewall part) directly. You should be able to NAT all of your LAN traffic through the tun0 interface, eventually combined with a rule to deny LAN traffic going out directly when the VPN interface is down.

Regards,
Guillaume
 
  • Thanks
Reactions: Ult
Hello,

I wrote a blog article about that point precisely. Check at step 9 (firewall part) directly. You should be able to NAT all of your LAN traffic through the tun0 interface, eventually combined with a rule to deny LAN traffic going out directly when the VPN interface is down.

Regards,
Guillaume

Okay! A new problem, that I should probably start a new thread for, but it is relevant. I had more or less nearly everything the guide suggested by Guillaume, I have FreeBSD behind a customer grade router. The firewall works perfectly, however I found that there are some services (mainly web sites that I host) that absolutely can not work behind the VPN. So what I am looking for is some some feedback, and possibly assistance setting this up to port forward properly. Here are some ideas I came up with after googling.

igb0 = physical WAN port
tun0 = VPN

Possible options:
  1. Port Forward incoming services on igb0 using static routes?
  2. Rebuild kernel with option ROUTETABLES=2 and use table 1 for tun0, table 2 for igb0 only for port forwarding.
  3. and on... A better suggestion.
I think option 2 is the correct way for addressing my issue and looks like it will be the easiest (I think) way to work around the VPN for port forwarding.
 
Hello,

The article I have written is indeed to provide an outbound VPN connection for a LAN behind the router, without hosting any server accessible from the Internet. For your needs, I suppose you could first enable port-forwarding on your ISP modem router, and forward ports HTTP (80) and/or HTTPS (443) to your FreeBSD router. Then on your FreeBSD router, modify pf.conf as to not NAT into your VPN your web site outbound traffic, it should goes out straight. I imagine something like this (it's just an extract of a modified pf.conf):
Code:
lan="re0"
egress="re1" # igb0 apparently for your setup
vpn="tun0"
web_server="10.0.0.10"
table <lan_network> { $lan:network, !$web_server }

# LAN goes through VPN, Web server goes out straight
nat on $vpn from <lan_network> to any -> ($vpn:0)
nat on $egress from $web_server to any -> $egress

# Prevent VPN bypass for LAN, allow Web server
block out quick log on $egress from <$lan_network> to any

# Allow incomming connections to the Web server
pass in quick on $egress from any to $web_server port 80 keep state

I never tried that kind of setup honestly, so I have no idea if it is the good way to go, and if it's working. If the routing table netstat -r forces your web server outbound connections to pass through your VPN, it is indeed a problem.

EDIT: I did a quick test on my router, and I seem not to be able to bypass my VPN, as it's the default route. Sorry I tried :)

Regards,
Guillaume
 
  • Thanks
Reactions: Ult
Yeah, that's what I thought would happen, and why I was thinking of doing ROUTETABLES=2. I think with a 2nt second table I could have the two default routes (at least I'm hoping it will work that way). I'm going to try and conjure something up today.

Thanks for trying Guillaume I'll post back if I get it going =]
 
I wanted to post back to say that I am for sure on the right path. ROUTETABLES=2 will work. I am still trying to set up the right pf rules, but to explain all I did, rebuild kernel then in rc.conf add

Code:
defaultrouter="$10.0.0.1 -fib 0,1"

This will set both tables to the same gateway at reboot. To test I started OpenVPN and in the pf.conf:

Code:
# Standard rules
pass out quick inet modulate state rtable 1
pass in quick on $lan rtable 1
and now everything is going in and out on WAN instead of tun0.


I am still working on the rules.iv I've been working at this all day and feel like I didn't make much progress but I will prevail!
 
It is a rough statement but I have it working. Not sure if it is optimal just yet, going to try a few more things but this DOES work the way I intended. I am sure all the traffic will not go through the VPN, including traffic I want to go to the VPN.

Code:
# Standard rules
pass out quick inet modulate state rtable 1
pass in quick on $lan

I have no idea how this is working, I had thought that pass out would be outgoing traffic. For some reason it has an opposite effect. I am guessing when a packet comes in it is routed correctly on both interfaces but, then going back out it is using rtable 1. I have no idea how my web browsing is going through the VPN.

I'm going to poke a bit more but if anyone has a better understanding and is able to explain the negative impacts this will cause with examples of services and such that would be great!
 
From pf.conf():
rtable <number>
Used to select an alternate routing table for the routing lookup. Only effective before the route lookup happened, i.e. when filtering inbound.

The way I see it you can choose to route your inbound LAN traffic to your VPN interface (rtable 0?) while letting the ountbound traffic going through your additional routing table (rtable 1?) where there is no VPN. I don't know how your routing tables are used, it may be the opposite. You should check both tables and ensure on which one your VPN is. You cannot apply rtable on an outbound rule apparently.

Guillaume
 
  • Thanks
Reactions: Ult
I was able to bypass my VPN without recompiling the kernel to have two routing tables. I'm using the route-to action from pf to route my computer traffic to my router outbound interface re1 instead of my VPN interface tun0. Below is an extract of the rules:
Code:
lan="re0"
egress="re1"
lan_ip="10.0.0.1"
egress_ip="192.168.1.2"
gateway="192.168.1.1"
vpn="tun0"
admin="10.0.0.52" # my test computer
table <lan_network> { $lan:network, !$admin }

# All LAN and router traffic coming to VPN interface are NATted (except admin computer)
nat on $vpn from <lan_network> to any -> ($vpn:0)

# If admin traffic comes to outbound interface, NAT it
nat on $egress from $admin to any -> $egress

# Prevent VPN bypass for LAN (except admin)
block out quick log on $egress from <lan_network> to any

# Route incomming admin traffic on lan interface to egress interface instead of VPN, and specify the gateway address (ISP router)
pass out quick inet modulate state
pass in quick on $lan route-to ( $egress $gateway ) proto tcp from $admin to any port 80
pass in quick on $lan

For outbound traffic, in the case of your web server, I suppose the route-to brother, reply-to, should be used.

Guillaume
 
  • Thanks
Reactions: Ult
That works quite nicely! I was about to just create a proxy on the LAN but I would much rather get pf working correctly for my needs.

I am trying to get reply-to to work now but I'm not quite sure what I'm missing. Tried many of different ways but here is what I think should be working.

Code:
pass in quick on $egress reply-to ( $lan $lan_ip ) proto { tcp, udp } from any to $webserver port 80

I have a long way to go to become a pf god like you Gulliaume.
 
pass in quick on $egress reply-to ( $lan $lan_ip ) proto { tcp, udp } from any to $webserver port 80

Maybe try this way?
Code:
pass in quick on $egress reply-to ( $egress $egress_gateway ) proto tcp from any to $webserver port { 80 443 } keep state

I never used this kind of pf rule, but from what I have found on the Internet it should be the way to go. Replace $egress_gateway with your ISP modem/router's private IP address.

I have a long way to go to become a pf god like you Gulliaume.
I am far from it! I am just playing around with pf, sometimes it works, sometimes not :) Reading man pages and doing searches on the Internet too, and when I don't know am asking here too. That is what a community is for ;)
 
  • Thanks
Reactions: Ult
Still no goal. I was thinking maybe a double route-to would work but I still can't get that working right either =[
 
After watching tcpdump (a lot) with pftop the reason reply-to is not working is because the rule doesn't seem to be applying to the packets. Maybe another rule is interfering? I can't figure it out, I keep hammering on this but don't seem to get anywhere.

I am moving to this to https://forums.freebsd.org/threads/reply-to-help.49174/ Hopefully being in the firewall thread will get more attention.
 
I didn't figure out anything with reply-to but I have the issue maybe one of the base pass in, pass out rules. I finally decided (after many many hours) to get rid of the base rules and use pass all and BAM! it fixed all the seemlessly nothing issues I was having. Also whoever said pass out does nothing with rtables is flat out wrong. I have 3 servers 2 of them would only work properly with pass out, the last one with pass in. Im sure the issue I was having with reply-to was due to the base rules as well. I can now successfully port forward all the services I want and be behind the VPN for everything else!

Code:
pass all
pass out proto tcp from any to $webserver port { 80, 443 } modulate state rtable 1
pass in proto tcp from $webserver port { 80, 443 } to any rtable 1
 
I'm happy you have a working setup :) I replied to you in the other thread you opened. The point about rtable and outbound rules is written in the man page, maybe I misunderstood it.

rtable <number>
Used to select an alternate routing table for the routing lookup. Only effective before the route lookup happened, i.e. when filtering inbound.
 
  • Thanks
Reactions: Ult
I read the same one and thought that exact same thing. thanks again for all your help =]
 
Back
Top