├── shorewall-zones.txt ├── shorewall-snat.txt ├── wg-down.sh ├── wg-routing.service ├── shorewall-interfaces.txt ├── wg.conf ├── shorewall-policy.txt ├── wg-up.sh ├── dhcpd.conf ├── WireGuard policy based routing per subnet using tables.txt ├── shorewall-rules.txt ├── LICENSE.MD └── README.md /shorewall-zones.txt: -------------------------------------------------------------------------------- 1 | fw firewall 2 | net ipv4 3 | loc ipv4 4 | dmz ipv4 5 | wg ipv4 -------------------------------------------------------------------------------- /shorewall-snat.txt: -------------------------------------------------------------------------------- 1 | MASQUERADE 192.168.1.0/24 azirevpn-uk1 2 | MASQUERADE 192.168.2.0/24 [WAN interface] 3 | -------------------------------------------------------------------------------- /wg-down.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | ip link set down dev azirevpn-uk1 3 | ip link del dev azirevpn-uk1 4 | ip rule del unicast iif [WAN interface] table vpn 5 | -------------------------------------------------------------------------------- /wg-routing.service: -------------------------------------------------------------------------------- 1 | #An example systemd service, which will execute our script to bring up the WireGuard VPN interface, add the VPN routing table, and set its routes. 2 | [Unit] 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/root/wg-up.sh 7 | 8 | [Install] 9 | WantedBy=default.target 10 | -------------------------------------------------------------------------------- /shorewall-interfaces.txt: -------------------------------------------------------------------------------- 1 | net NET_IF tcpflags,dhcp,nosmurfs,routefilter,logmartians,sourceroute=0,physical=[WAN interface] 2 | loc LOC_IF tcpflags,dhcp,nosmurfs,routefilter,routeback=1,logmartians,physical=[LAN interface] 3 | dmz DMZ_IF tcpflags,dhcp,nosmurfs,routefilter,routeback=1,logmartians,physical=[DMZ interface] 4 | wg azirevpn-uk1 5 | -------------------------------------------------------------------------------- /wg.conf: -------------------------------------------------------------------------------- 1 | # An example .conf file to live in /etc/wireguard. Ensure you fill in the correct details (private key, server public key and tunnel address) from the .conf file your provider gives you. 2 | 3 | [Interface] 4 | PrivateKey = [your private key here] 5 | 6 | [Peer] 7 | PublicKey = [peer public key here] 8 | AllowedIPs = 0.0.0.0/0 9 | Endpoint = uk1.wg.azirevpn.net:51820 10 | -------------------------------------------------------------------------------- /shorewall-policy.txt: -------------------------------------------------------------------------------- 1 | $FW net ACCEPT 2 | $FW loc ACCEPT 3 | $FW dmz ACCEPT 4 | $FW wg ACCEPT 5 | 6 | loc net ACCEPT 7 | loc $FW ACCEPT 8 | loc dmz ACCEPT 9 | loc wg ACCEPT 10 | 11 | dmz net ACCEPT 12 | 13 | wg $FW ACCEPT 14 | 15 | net all DROP info 16 | 17 | # THE FOLLOWING POLICY MUST BE LAST 18 | all all REJECT $LOG_LEVEL 19 | -------------------------------------------------------------------------------- /wg-up.sh: -------------------------------------------------------------------------------- 1 | # A script to bring up the WireGuard VPN interface, and set up the VPN routing table (with rules for the correct subnet). 2 | 3 | #!/usr/bin/bash 4 | ip link add dev azirevpn-uk1 type wireguard 5 | ip address add dev azirevpn-uk1 10.20.xx.xx/19 6 | wg setconf azirevpn-uk1 /etc/wireguard/azirevpn-uk1.conf 7 | ip link set up dev azirevpn-uk1 8 | ip rule add unicast iif [WAN interface] table vpn 9 | ip route add default dev azirevpn-uk1 via 10.xx.xx.xx table vpn 10 | ip route add 192.168.2.0/24 via 192.168.2.1 dev [LAN interface] table vpn 11 | -------------------------------------------------------------------------------- /dhcpd.conf: -------------------------------------------------------------------------------- 1 | #example barebones dhcpd.conf for two subnets - LAN and DMZ 2 | 3 | authoritative; 4 | 5 | # LAN clients. 6 | 7 | subnet 192.168.1.0 netmask 255.255.255.0 { 8 | range 192.168.1.11 192.168.1.254; 9 | default-lease-time 600; 10 | max-lease-time 7200; 11 | 12 | host your-pc { 13 | hardware ethernet a0:b2:00:00:00:00; 14 | fixed-address 192.168.1.2; 15 | } 16 | 17 | host your-laptop { 18 | hardware ethernet c0:d1:00:00:00:00; 19 | fixed-address 192.168.1.3; 20 | } 21 | 22 | option domain-name-servers 192.168.1.1; 23 | option subnet-mask 255.255.255.0; 24 | option routers 192.168.1.1; 25 | option domain-name "example.com"; 26 | option broadcast-address 192.168.1.255; 27 | } 28 | 29 | # DMZ clients. 30 | 31 | subnet 192.168.2.0 netmask 255.255.255.0 { 32 | range 192.168.2.11 192.168.2.254; 33 | default-lease-time 600; 34 | max-lease-time 7200; 35 | 36 | host your-server { 37 | hardware ethernet e4:f5:00:00:00:00; 38 | fixed-address 192.168.2.2; 39 | } 40 | 41 | option domain-name-servers 192.168.2.1; 42 | option subnet-mask 255.255.255.0; 43 | option routers 192.168.2.1; 44 | option domain-name "example.com"; 45 | option broadcast-address 192.168.2.255; 46 | } 47 | -------------------------------------------------------------------------------- /WireGuard policy based routing per subnet using tables.txt: -------------------------------------------------------------------------------- 1 | # This allows you to tunnel only one subnet (physical interface) and leave the other - i.e. DMZ - attached directly to the internet. 2 | # It's not necessary to do this manually as the wg-up.sh script does it for us. I add this for reference, and to show how it works. 3 | # First, add a VPN routing table: 4 | 5 | echo "10 vpn" >> /etc/iproute2/rt_tables 6 | 7 | # Next, add the following policy rule for the LAN interface you want to route via VPN: 8 | 9 | ip rule add unicast iif [LAN interface] table vpn 10 | 11 | # This rule tells the system that any traffic coming in from LAN interface xyz should look to table VPN for its routes. 12 | 13 | # You can check the rules with ip rule show: 14 | 15 | ip rule show 16 | 0: from all lookup local 17 | 32765: from all iif xyz lookup vpn 18 | 32766: from all lookup main 19 | 32767: from all lookup default 20 | 21 | #The rules are applied in ascending order, until a rule matches. If a packet is received on interface xyz, rule 32765 matches, else the next rules are tried. 22 | 23 | #You can now add routes to the vpn routing table. For example, to add a default route (from LAN subnet on xyz) to your tunnel: 24 | 25 | ip route add default dev azirevpn-uk1 via 10.20.xx.xx table vpn 26 | ip route add 192.168.2.0/24 via 192.168.2.1 dev [DMZ interface] table vpn 27 | 28 | # To print the vpn routing table so you can check it, use 29 | 30 | ip route show table vpn 31 | -------------------------------------------------------------------------------- /shorewall-rules.txt: -------------------------------------------------------------------------------- 1 | DNS(ACCEPT) loc $FW 2 | DNS(ACCEPT) dmz $FW 3 | # 4 | # Accept WireGuard 5 | ACCEPT net $FW udp 51820 6 | # Accept SSH connections from the local network to the firewall and DMZ servers 7 | # 8 | SSH(ACCEPT) loc $FW 9 | SSH(ACCEPT) loc dmz 10 | # 11 | # Drop Ping from the "bad" net zone. 12 | 13 | Ping(DROP) net $FW 14 | # 15 | # Make ping work bi-directionally between the dmz, net, Firewall and local zone 16 | # (assumes that the loc-> net policy is ACCEPT). 17 | # 18 | Ping(ACCEPT) loc $FW 19 | Ping(ACCEPT) dmz $FW 20 | Ping(ACCEPT) net $FW 21 | Ping(ACCEPT) loc dmz 22 | Ping(DROP) dmz loc 23 | Ping(ACCEPT) dmz net 24 | 25 | ACCEPT $FW net icmp 26 | ACCEPT $FW loc icmp 27 | ACCEPT $FW dmz icmp 28 | 29 | # Uncomment this if using Proxy ARP and static NAT and you want to allow ping from 30 | # the net zone to the dmz and loc 31 | 32 | #Ping(ACCEPT) net dmz 33 | #Ping(ACCEPT) net loc 34 | 35 | # DNAT port forwards - add more as required, following this template. It's necessary to add the loc and dmz entries to allow local clients to also access your servers (via local IP or domain name) from inside the network. Adding only the 'net' entry would only allow access to people outside your network, unless you enable hairpin NAT. This solution is better, as hairpin NAT necessitates putting local traffic through the firewall as though it came from outside. 36 | 37 | DNAT loc dmz:192.168.2.5 tcp 80 - [WAN_IP] 38 | DNAT dmz dmz:192.168.2.5 tcp 80 - [WAN_IP] 39 | DNAT net dmz:192.168.2.5:80 tcp 80 40 | -------------------------------------------------------------------------------- /LICENSE.MD: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WireGuard x86 edge router, using Arch Linux 2 | How to make a fully functional Arch Linux edge router, with stateful firewall and NAT, running WireGuard VPN. 3 | 4 | This readme has been cobbled together in an hour because I didn't want to just post my reference files without comment. This guide will be fleshed out and formatted nicely over the coming day(s) as I get the opportunity **[It never was, but I'm glad some people found it useful!]**, and will ultimately include full copies of all referenced config files etc. For now, anyone who is attempting this project should have a fair understanding of Linux anyway, so I assume you know how to parse my cut down config example files and amend your own (full versions) to match. 5 | 6 | I also start this guide by assuming that you are running the latest Arch Linux, you are using AzireVPN as your VPN provider, and you have at least three physical interfaces - WAN, LAN and DMZ (for your NAS/servers). You can amend this guide easily to account for any differences. 7 | 8 | For now, in essence: 9 | 10 | Install the latest Arch Linux, following the Arch Wiki's installation guide if necessary. You may wish to consider a switch to the `linux-lts` and `linux-lts-headers` kernel to save updates needing reboots as often as time goes on. Just add them, remove the normal linux package, and then regenerate the GRUB config file. Next time you reboot you're on LTS (or hardened, or whatever). 11 | 12 | I also assume that as part of that process you have set up your local network interfaces using netctl profiles (which live in `/etc/netctl`), and then enabled and started them. I'm using a repurposed Dell Optiplex 7010 from eBay with an additional low profile Intel Pro 1000 VT quad port server NIC, so my netctl profiles are `/etc/netctl/WAN`, `./LAN`, and `./DMZ`. They are enabled and started like this: 13 | 14 | ```shell 15 | netctl enable eno1 #WAN 16 | ``` 17 | ```shell 18 | netctl enable enp3s0f0 #LAN 19 | ``` 20 | ```shell 21 | netctl enable enp3s0f1 #DMZ 22 | ``` 23 | ```shell 24 | netctl start emo1 25 | ```` 26 | ```shell 27 | netctl start en3ps0f0 28 | ``` 29 | ```shell 30 | netctl start en3ps0f1 31 | ``` 32 | 33 | In future, netctl will bring up and handle the interfaces by itself. 34 | 35 | Now the basics are out of the way, we install the basic requirements for this project: 36 | 37 | ```shell 38 | pacman -S dhcp shorewall dnscrypt-proxy linux-headers wireguard-tools wireguard-dkms jq resolvconf iperf3 glances openssh 39 | ``` 40 | 41 | After a reboot, put your AzireVPN (or other) .conf file in `/etc/wireguard`. Edit it to remove references to DNS, add your private key and your provider's public key and endpoint, and have it wind up matching the example in this repo. 42 | 43 | Next, edit `/etc/dnscrypt-proxy/dnscrypt-proxy.toml` to enable the service on your interfaces (e.g. `127.0.0.1:53`, `192.168.1.1:53`, `192.168.2.1:53`). Enable whichever servers you prefer, for example Cloudflare and Quad9 - or whatever. Then enable dnscrypt-proxy: 44 | 45 | ```shell 46 | systemctl enable --now dnscrypt-proxy 47 | ``` 48 | 49 | Next we need to tell Shorewall what to do. For simplicity's sake, first copy over the Three Interfaces example from the Shorewall documentation like this: 50 | 51 | ```shell 52 | cp /usr/share/doc/shorewall/Samples/three-interfaces/* /etc/shorewall/ 53 | ``` 54 | 55 | Edit the files in the `/etc/shorewall` directory as per the conf files in this repo. In essence, you need to edit the `./interfaces` file to list your interfaces by name, outline your network segments in `./zones`, tell Shorewall who can talk with whom using `./policy` and set up `./rules` with any necessary changes. Finally we set the `./snat` file to tell Shorewall that our LAN subnet should `MASQUERADE` via our VPN, and the DMZ zone should `MASQUERADE` via the WAN IP. 56 | 57 | My example rules config file in this repo gives examples for allowing SSH from local clients only, and using DNAT to allow people on the internet as well as LAN and DMZ clients to access servers on local machines (without having to hairpin back through the firewall). Once this is done, we can enable and start shorewall: 58 | 59 | ```shell 60 | systemctl enable --now shorewall 61 | ``` 62 | 63 | Then we need to set up dhcpd to serve our local clients with DHCP IP addresses (the ones who aren't issued static IPs, anyway). Edit `/etc/dhcpd.conf` and use the repo's example .conf file as a guide. Start it with `authoritative;` and amend the subnets to your liking (eg `172.16.32.0/24` instead of `192.168.1.0/24` or whatever). You can flesh out the example static IP hosts as or if required. Then start and enable the DHCPD's server: 64 | 65 | ```shell 66 | systemctl enable --now dhcpd4 67 | ``` 68 | 69 | At this point, you may wish to configure and enable SSH so you can administer your router from elsewhere on your network. This is especially useful if (likely) you are to run the router headless. If you get stuck, check out the Arch SSH wiki, but in essence just edit `/etc/ssh/sshd.conf` to uncomment the port and to allow root login if required (only do this if not allowing WAN access to SSH, and even then it's probably a bad idea). Hardening SSH is beyond the scope of this guide (for now), but I can recommend `sshguard`. 70 | 71 | Now we have the ability to form WireGuard tunnels, `dnscrypt-proxy` to resolve DNS for local clients, `dhcpd` to issue and track IP addresses, and `shorewall` to keep everything running smoothly and safely. With regards to bringing up and down the WireGuard tunnel itself, I don't use the `wg-quick` utility as it overwrites rules and makes its own tables - which in my particular case intefered with my preferred routing for my DMZ subnet. Instead I made two very simple shell scripts, `wg-up.sh` and `wg-down.sh`, which are fairly self-explanatory. 72 | 73 | Specifically, `wg-up.sh` brings up a WireGuard interface to AzireVPN (in my case). It then adds a table called `VPN` to `iproute2`'s `rt_tables`, and adds rules to it so that all traffic on my LAN subnet looks up this table. The rules in this table say: 74 | 75 | ```shell 76 | ip rule add unicast iif {LAN interface} table vpn 77 | ``` 78 | ```shell 79 | ip route add default dev azirevpn-uk1 via 10.xx.xx.xx table vpn 80 | ``` 81 | ```shell 82 | ip route add 192.168.2.0/24 via 192.168.2.1 dev {DMZ interface} table vpn 83 | ``` 84 | 85 | This basically means if you're on my LAN you get sent to the WireGuard tunnel and everything is protected by the VPN. That is, however, unless you wish to access a machine on the DMZ subnet (`192.168.2.0/24`). In this case you're sent there directly by the router, bypassing the VPN. Everyone else (the firewall, the DMZ zone clients) get sent directly over WAN and bypass the tunnel. This was necessary for me to keep my servers running properly (Plex, SABnzbd, Sonarr etc) and be able to reach them using mydomain.com over the internet. 86 | 87 | This is all very well and good, but bringing up the WireGuard interface, adding tables, fleshing out that table with rules and so on is time consuming. That's where my script comes in. I made a systemd unit to launch the `wg-up.sh` script on boot. Now any time my router (re)starts, within 10 seconds everything is up and online, and my WireGuard tunnel is ready for action too. Seamless! 88 | 89 | To make the systemd service, make a file called wg-up.service (or whatever) and place it in `/etc/systemd/system/` with its contents as per the example file in this repo. Don't forget to place your scripts in `/root/` or else to amend the content of the service file to point to the right location. Then enable the service like any other, so it comes up at boot in future: 90 | 91 | ```shell 92 | systemctl enable --now wg-up.service 93 | ``` 94 | 95 | If for any reason you want/need to restart your tunnel, you can just issue `/root/wg-down.sh` and then invoke your startup service again: 96 | 97 | systemctl restart wg-up.service 98 | 99 | If you want to see the status of your WireGuard VPN tunnel you can always issue the ever-useful command `wg`. It's as simple as that. To test that things are working nicely, you can do the following *from the router itself*: 100 | 101 | ```shell 102 | curl ipinfo.io #Should return WAN IP 103 | ``` 104 | ```shell 105 | curl ipinfo.io --interface azirevpn-uk1 #Should return AzireVPN's IP 106 | ``` 107 | 108 | We're all done! Now you should have a barebones, fully functional, powerful, stateful firewall with (D/S)NAT, WireGuard, network segregation between LAN and servers/CCTV/etc for security, and all the great tools (like `iperf3`, `traceroute`, `dig`, `ping`, `glances`, etc) that Linux affords. 109 | 110 | My own little Arch Router has been up for several ~~days~~ years now. I have two switches (one coming out of the LAN interface and one coming out of the DMZ interface), and my Unifi UAC AP PRO access point is plugged into the DMZ zone's PoE switch. The AP runs an SSID for us to use, and a captive portal for guests to our home, which is cut off from everything and everyone else. This provides convenience and security in one step. If we have a gathering (eg Christmas) I just put up a piece of paper with the WiFi SSID and password, and the relevant QR code underneath so people can just hop onto the guest WiFI without asking. 111 | 112 | You can see a little topology diagram of my network as it was when I first posted this repo (sans some recent changes like IPs, and my wireless AP is now in DMZ) here: 113 | 114 | ![My old network topology](https://i.imgur.com/6GAEsGf.png) 115 | 116 | I'll tidy it up at some point to reflect the new reality of my network, but it still gives you a nice visual idea of what this guide accomplishes. Finally here's a speedtest from a LAN client using the WireGuard tunnel (with some wifi users browsing, so slightly low - you get the idea though): 117 | 118 | ![Speedtest.net result using the Arch router](https://www.speedtest.net/result/7878355703.png) 119 | 120 | So far on my 'router', the average load is 0.00 (lol). It puts through my full ISP line speed (380Mbs) without breaking double digits CPU usage (even via WireGuard - which spreads the load beautifully over the i7's 8 threads), and is using about 125MB RAM. Overkill? Certainly. Fun? Absolutely. Future-proof? Hell yeah. Try it out and let me know how you find it! 121 | 122 | ## Update 123 | This router ran a couple of years for me, before I moved to vanilla BSD. It shovelled WireGuard over gigabit just as well as it did my old 380Mbps plan, and never went wrong. Kudos. 124 | These days, I'm on gigabit WAN and have a single x86 BSD edge router, a managed L2/L3 core switch, a Ruckus R710 Wireless AP managing guest isolation, and one flat subnet. I'm happy to see this guide helped a few people achieve similar goals. 125 | --------------------------------------------------------------------------------