[DRAFT] open to comments
Goal
Step 1: Setting up Jail with NAT and port-forwarding (local <-> jail)
a. Go to Jail wizard and switch to "Advance Mode"
b. Enable NAT, VNET and (optional) set default iface to your NIC, in my case: bg0
c. Under network properties set "NAT Port-forwarding" as shown. You can leave "NAT Interface" empty as in my case the jail picks bge0 as default at start-up
Note:
- If bge0 has IP 192.168.20.2 then your Jail wireguard server will listen on 192.168.20.2:51820
d. Jail properties enable "allow_tun"
e. Save your jail config
Step 2: Install Wireguard
a. Enter your jail
b. Setup "pkg" to upgrade against latest base
c. Paste the below setup, press Ctrl+X, and "Yes"
d. upgrade your base to the latest
e. install wireguard
Step 3: Set up wireguard & Jail networking (jail <-> wireguard)
a. Enable Wireguard iface, NAT & IP forwarding in "rc.conf"
b. ensure the following lines exist in your rc.conf
c. Create the ipfw.rules file
d. Paste the below lines into the file, Ctrx+X and "Yes"
Note: I have commented most rules out for the basic/simple config however feel free to uncomment and experiment if you need a more complex filtering.
e. Using in-kernel NAT requires to disable TCP segmentation offloading (TSO). Set the following in Jail's /etc/sysctl.conf
f. Restart the Jail & go get back to the console
g. Confirm firewall settings loaded. Note: The above config of ipfw rules should look like this
Step 3: Setup Wireguard Server & remote host configs
a. Create public/private key pairs for wireguard server and remote host
b. Create Wireguard server config
c. Add the Server (interface) and remote (peer) by pasting the below config, then press Ctrl+X & "Yes"
d. Start Wireguard service
Step 5: Setup wireguard on remote host
a. Create remote host config
b. Add the following lines with the relevant values, press Ctrl+X and "yes".
Note:
- [Interface] address should match the [Peer] value in server's wg.conf;
- DNS entry can is optional
- Allowed IPs can be limited to the remote subnet e.g 192.168.0.0/24
as an example your remote conf could look like this
c. Install wireguard on remote host and load the remote host config file using QR scan code (easier)
Step 6: Setup port-forwarding on your router
a. Setup port-forwarding on your router so
Step 7: Confirm VPN connectivity
a. Activate VPN connection from the remote host. You should be able to see something like this on your server if all setup correctly
References
[1] https://genneko.github.io/playing-with-bsd/networking/freebsd-wireguard-jail/
[2] https://www.freebsd.org/doc/handbook/firewalls-ipfw.html
[3] https://sirtoffski.github.io/docs/freebsd-ipfw/
Goal
- To setup a VPN server based on the Wireguard technology and running from within a Jail.
- The VPN server would allow remote devices to connect and access resources in the local network
- All remote traffic should be routed via the VPN channel
- [1] The FreeNas host is running on the local network 192.x.x.x/24 using the bge0 iface
- [2] The Jail is setup with VNET and network 172.x.x.x/24
- [3] Since Wireguard will be running from within the Jail's network (e.g. 10.x.x.x/32:51820) we'll need to expose the Wireguard listening port outside the Jail (192.x.x.x:51820) , hence we need
- NAT active on VNET
- port-forwarding for 192.x.x.x:51820 (local) <-->172.x.x.x/24 (jail)
- Firewall rules on Jail for 172.x.x.x:51820 (jail) <--> 10.x.x.x:51820 (wireguard)
- [4] Finally port-forwarding from WAN <---> 192.x.x.x:51820
Step 1: Setting up Jail with NAT and port-forwarding (local <-> jail)
a. Go to Jail wizard and switch to "Advance Mode"
b. Enable NAT, VNET and (optional) set default iface to your NIC, in my case: bg0
c. Under network properties set "NAT Port-forwarding" as shown. You can leave "NAT Interface" empty as in my case the jail picks bge0 as default at start-up
Note:
- If bge0 has IP 192.168.20.2 then your Jail wireguard server will listen on 192.168.20.2:51820
d. Jail properties enable "allow_tun"
e. Save your jail config
Step 2: Install Wireguard
a. Enter your jail
# iocage console << your jail name >>
b. Setup "pkg" to upgrade against latest base
Code:
# pkg install nano # mkdir -p /usr/local/etc/pkg/repos # nano /usr/local/etc/pkg/repos/FreeBSD.conf
c. Paste the below setup, press Ctrl+X, and "Yes"
Code:
FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest", mirror_type: "srv", signature_type: "fingerprints", fingerprints: "/usr/share/keys/pkg", enabled: yes }
d. upgrade your base to the latest
# pkg upgrade
e. install wireguard
# pkg install wireguard wireguard-go libqrencode
Step 3: Set up wireguard & Jail networking (jail <-> wireguard)
a. Enable Wireguard iface, NAT & IP forwarding in "rc.conf"
# nano /etc/rc.conf
b. ensure the following lines exist in your rc.conf
Code:
# Enable Wireguard wireguard_enable="YES" wireguard_interfaces="wg0" #Enable ip forwarding gateway_enable="YES" #Enable Firewall NAT in kernel mode firewall_enable="YES" firewall_nat_enable="YES" #firewall_logging="YES" # Optional firewall_script="/usr/local/etc/ipfw.rules"
c. Create the ipfw.rules file
# nano /usr/local/etc/ipfw.rules
d. Paste the below lines into the file, Ctrx+X and "Yes"
Note: I have commented most rules out for the basic/simple config however feel free to uncomment and experiment if you need a more complex filtering.
Code:
#!/bin/sh # ipfw config/rules # from FBSD Handbook, rc.firewall, et. al. # Flush all rules before we begin. ipfw -q -f flush # Set rules command prefix cmd="ipfw -q add " # Internet-facing iface vif="epair0b" # Used for outboud NAT rules skip="skipto 1000" #### WG-specific Options #### # Listen Port wg_port="51820" # Subnet wg_subnet="10.0.0.1/32" # Wireguard interface, matching the name in /etc/wireguard/*.conf wg_iface="wg0" # Allow NAT ipfw disable one_pass ipfw -q nat 1 config if $vif same_ports unreg_only reset # allow all for localhost $cmd 00010 allow ip from any to any via lo0 $cmd 00011 allow ip from any to any via $wg_iface # NAT-specifig rules $cmd 00099 reass all from any to any in # reassamble inbound packets $cmd 00100 nat 1 ip from any to any in via $vif # NAT any inbound packets # checks stateful rules. If marked as "keep-state" the packet has # already passed through filters and is "OK" without futher # rule matching $cmd 00101 check-state # allow WG #$cmd 00233 $skip udp from any to any src-port $wg_port out via $vif keep-state #$cmd 00234 $skip udp from $wg_subnet to any out via $vif keep-state #$cmd 00235 $skip tcp from $wg_subnet to any out via $vif setup keep-state #$cmd 00320 $skip udp from any to any out via $vif keep-state #$cmd 00325 $skip tcp from any to any out via $vif setup keep-state #$cmd 00330 $skip icmp from any to any out via $vif keep-state #$cmd 999 deny ip from any to any # NAT $cmd 1000 nat 1 ip from any to any out via $vif # skipto location for outbound stateful rules #$cmd 1001 allow ip from any to any
e. Using in-kernel NAT requires to disable TCP segmentation offloading (TSO). Set the following in Jail's /etc/sysctl.conf
Code:
net.inet.tcp.tso="0"
f. Restart the Jail & go get back to the console
Code:
# exit # iocase restart <<wireguard jail>> * Stopping wireguard + Executing prestop OK + Stopping services OK + Tearing down VNET OK + Removing devfs_ruleset: 10 OK + Removing jail process OK + Executing poststop OK wireguard: nat requires nat_interface, using bge0 * Starting wireguard + Started OK + Using devfs_ruleset: 6 + Configuring VNET OK + Using IP options: vnet + Starting services OK + Executing poststart OK # iocase console <<wireguard jail>>
g. Confirm firewall settings loaded. Note: The above config of ipfw rules should look like this
Code:
# ipfw list 00010 allow ip from any to any via lo0 00011 allow ip from any to any via wg0 00099 reass ip from any to any in 00100 nat 1 ip from any to any in via epair0b 00101 check-state :default 01000 nat 1 ip from any to any out via epair0b 65535 allow ip from any to any # ipfw nat show config ipfw nat 1 config if epair0b same_ports unreg_only reset
Step 3: Setup Wireguard Server & remote host configs
a. Create public/private key pairs for wireguard server and remote host
Code:
# cd /usr/local/etc/wireguard/ # wg genkey | tee wg.private | wg pubkey > wg.public # wg genkey | tee remote.private | wg pubkey > remote.public
b. Create Wireguard server config
# nano wg0.conf
c. Add the Server (interface) and remote (peer) by pasting the below config, then press Ctrl+X & "Yes"
Code:
[Interface] Address = 10.0.0.1/32 PrivateKey = << Paste wg.private here >> ListenPort = 51820 [Peer] PublicKey = << Paste remote.public here >> AllowedIPs = 10.0.0.2/32
d. Start Wireguard service
Code:
# service wireguard start [#] wireguard-go wg0 INFO: (wg0) 2020/07/09 22:35:10 Starting wireguard-go version 0.0.20200320 [#] wg setconf wg0 /tmp/tmp.xw963cv4/sh-np.h2wle2 [#] ifconfig wg0 inet 10.0.0.1/32 10.0.0.1 alias [#] ifconfig wg0 mtu 1420 [#] ifconfig wg0 up [#] route -q -n add -inet 10.0.0.2/32 -interface wg0 [+] Backgrounding route monitor
Step 5: Setup wireguard on remote host
a. Create remote host config
# nano remote.conf
b. Add the following lines with the relevant values, press Ctrl+X and "yes".
Note:
- [Interface] address should match the [Peer] value in server's wg.conf;
- DNS entry can is optional
- Allowed IPs can be limited to the remote subnet e.g 192.168.0.0/24
Code:
[Interface] Address = 10.0.0.2/32 PrivateKey = << your remote.private key here >> DNS = 8.8.8.8 [Peer] PublicKey = << your wg.public key here >> AllowedIPs = 0.0.0.0/0,::/0 Endpoint = << your WAN IP >>:<<WAN exposed port>>
as an example your remote conf could look like this
Code:
[Interface] Address = 10.0.1.2/32 PrivateKey = 8Ng/rzsuTlbZobnRqp2XC2bOgZP29P0K8d2Oa9m9pUA= DNS = 192.168.1.1 [Peer] PublicKey = bAUcryyyQ1x95zR27pMO7kwuskLpYM6fCOC211111gE= AllowedIPs = 0.0.0.0/0,::/0 Endpoint = 242.72.48.124:51820
c. Install wireguard on remote host and load the remote host config file using QR scan code (easier)
Code:
# qrencode -t ansiutf8 < remote.conf
Step 6: Setup port-forwarding on your router
a. Setup port-forwarding on your router so
<<WAN_IP>>:51820 <---> <<bge0_ip>>:51820
Step 7: Confirm VPN connectivity
a. Activate VPN connection from the remote host. You should be able to see something like this on your server if all setup correctly
Code:
# wg show interface: wg0 public key: bAUcnaxxxx95zR27pxxxkwuskLpYM6fCOC219hz1gE= private key: (hidden) listening port: 51820 peer: ehISAoqcc1TuuuuuuuuoWGAr4yyyyyy5Oq8qU1i1SA= endpoint: 85.255.235.8:28431 allowed ips: 10.0.0.2/32 latest handshake: 13 hours, 45 minutes, 5 seconds ago transfer: 87.82 MiB received, 1.69 GiB sent
References
[1] https://genneko.github.io/playing-with-bsd/networking/freebsd-wireguard-jail/
[2] https://www.freebsd.org/doc/handbook/firewalls-ipfw.html
[3] https://sirtoffski.github.io/docs/freebsd-ipfw/