<p>With the increasing exhaustion of IPv4 addresses across the globe, various ISPs have resorted to implementing IPv4 Carrier Grade Network Address Translation (CG-NAT) as a solution to this problem.</p> <p>What this means is ISPs do not assign a publicly accessible IPv4 address to an end-user’s router and/or modem but rather a private IPv4 address that is behind a carrier network wide <abbr title="Network Address Translation">NAT</abbr> implementation.</p> <span id="continue-reading"></span> <p>For those who host servers on their home network or for just having remote access to the home network for CCTV access, etc. CG-NAT prevents this since one no longer has a publicly accessible IPv4 address and forwarding incoming requests through CG-NAT is incredibly hard, even if the ISP makes an effort of supporting extensions that allow this on their NAT implementation.</p> <p>The saving grace in this situation is that ISPs have at the same time started rolling out IPv6 addresses across their network which inherently does have public addressability down to the individual client devices via <a rel="noopener nofollow noreferrer external" target="_blank" href="https://en.wikipedia.org/wiki/Prefix_delegation">Prefix Delegation</a> built-in.</p> <p>However, we’re still a far way out from having IPv6 address availability and accessibility across every network throughout the globe. Especially on mobile devices with Android’s non-functioning/incompatible IPv6 stack, we need a fallback IPv4 addressing solution that works around CG-NAT.</p> <h2 id="wireguard"><a class="zola-anchor" href="#wireguard" aria-label="Anchor link for: wireguard">🔗</a> Wireguard</h2> <p>With the invention and implementation of <a rel="noopener nofollow noreferrer external" target="_blank" href="https://www.wireguard.com/">Wireguard</a> within the Linux kernel we don’t need to rely on complicated setups like NAT64, IPv6in4, IPv4in6, etc.</p> <p>With Wireguard we can have a setup where, we rent a <abbr title="Virtual Private Server">VPS</abbr> server with a public IPv4 address that we can connect to as a <abbr title="Virtual Private Network">VPN</abbr> client, and it routes our private home network requests to our actual home router across the public internet.</p> <p><img src="wireguard-vps.svg">Network Topology</img></p> <p>This can be achieved by having our home router connect and establish a connection with the VPS, since the VPS is the one having a public <strong>and</strong> static IPv4 address, which works flawlessly with CG-NAT since the router is making an outgoing connection and not waiting for an incoming connection. This solves a whole class of issues with CG-NAT, dynamic IP addresses and DDNS.</p> <h2 id="vps-configuration"><a class="zola-anchor" href="#vps-configuration" aria-label="Anchor link for: vps-configuration">🔗</a> VPS Configuration</h2> <p>To install Wireguard related packages and create private keys follow this <a rel="noopener nofollow noreferrer external" target="_blank" href="https://wiki.archlinux.org/title/WireGuard">guide</a>.</p> <p>For a more automated VPN setup on a cloud provider, checkout this <a rel="noopener nofollow noreferrer external" target="_blank" href="https://shalzz.gumroad.com/l/self-host-vpn">ansible script and guide</a> with a pre-setup cloud shell environment.</p> <p>The minimal configuration for getting the above solution working is as follows</p> <p>Here we are assuming your router creates and uses the 192.168.1.0/24 subnet for your home network. Correspondingly we create and use the 192.168.9.0/24 subnet space for the Wireguard network.</p> <p>The first peer we have below is our home router that connects with the <code>192.168.9.1</code> IP address and routes all home network i.e. <code>192.168.1.0/24</code> subnet requests to this peer.</p> <pre class="giallo" style="color: #657B83; background-color: #FDF6E3;" ><code data-lang="plain"><span class="giallo-l"><span># /etc/wireguard/wg0.conf</span></span> <span class="giallo-l"><span>[Interface]</span></span> <span class="giallo-l"><span>Address = 192.168.9.2/32</span></span> <span class="giallo-l"><span>ListenPort = 51871</span></span> <span class="giallo-l"><span>PrivateKey = <vps-privkey></span></span> <span class="giallo-l"></span> <span class="giallo-l"><span>[Peer]</span></span> <span class="giallo-l"><span>PublicKey = <router-pubkey></span></span> <span class="giallo-l"><span>AllowedIPs = 192.168.9.1/32, 192.168.1.0/24</span></span> <span class="giallo-l"></span> <span class="giallo-l"><span>[Peer]</span></span> <span class="giallo-l"><span>PublicKey = <peer1-pubkey></span></span> <span class="giallo-l"><span>AllowedIPs = 192.168.9.3/32</span></span> <span class="giallo-l"></span> <span class="giallo-l"><span>[Peer]</span></span> <span class="giallo-l"><span>PublicKey = <peer2-pubkey></span></span> <span class="giallo-l"><span>AllowedIPs = 192.168.9.4/32</span></span></code></pre> <p>You can create and add more peers to the above config in the similar fashion. You can also optionally create and add the <code>PreSharedKey</code> option to each peer for increased security, particularly quantum resistance.</p> <p>The peers, other than the home router peer, all directly connect to the VPS and by the way of IP forwarding can also connect to the home router and all devices on the home network.</p> <h2 id="home-router-configuration"><a class="zola-anchor" href="#home-router-configuration" aria-label="Anchor link for: home-router-configuration">🔗</a> Home Router Configuration</h2> <p>For the other side of the configuration on the home router, we just need to set up one peer that connects and persists the connection to the VPS wireguard server.</p> <p>This configuration is for the OpenWrt OS, if you’re using any other router OS you’ll have to adapt to its configuration format.</p> <pre class="giallo" style="color: #657B83; background-color: #FDF6E3;" ><code data-lang="plain"><span class="giallo-l"><span># /etc/config/network</span></span> <span class="giallo-l"><span>config interface 'wg0'</span></span> <span class="giallo-l"><span> option proto 'wireguard'</span></span> <span class="giallo-l"><span> option private_key '<router-privkey>'</span></span> <span class="giallo-l"><span> option listen_port '51820'</span></span> <span class="giallo-l"><span> list addresses '192.168.9.1/24'</span></span> <span class="giallo-l"></span> <span class="giallo-l"><span>config wireguard_wg0 'wgclient1'</span></span> <span class="giallo-l"><span> option public_key '<vps-pubkey>'</span></span> <span class="giallo-l"><span> list allowed_ips '192.168.9.0/24'</span></span> <span class="giallo-l"><span> option endpoint_host '<vps-public-ip-address>'</span></span> <span class="giallo-l"><span> option endpoint_port '51871'</span></span> <span class="giallo-l"><span> option persistent_keepalive '25'</span></span> <span class="giallo-l"><span> # set to 0 to disable home clients</span></span> <span class="giallo-l"><span> # from accessing the VPS peers directly</span></span> <span class="giallo-l"><span> option route_allowed_ips '1'</span></span></code></pre> <p>The <code>allowed_ips</code> or <code>AllowedIps</code> option of the wireguard config also acts as an ACL or access control method. So if we want to allow other peers, other than just the direct VPS peer <code>192.168.9.2</code>, to access this network we need to allow their IP addresses as well. We can do that by whilelisting the whole subnet with <code>192.168.9.0/24</code> or allow individual IP’s one by one.</p> <p>That last thing to do is to make sure the Wireguard interface (<code>wg0</code> in the example) is assigned to the <code>LAN</code> firewall zone for letting the wg peers access clients within the LAN zone (192.168.1.0/24).</p> <p>Run this command to do so on OpenWrt:</p> <pre class="giallo" style="color: #657B83; background-color: #FDF6E3;" ><code data-lang="shellscript"><span class="giallo-l"><span style="color: #586E75;font-weight: bold;">export</span><span style="color: #268BD2;"> WG_INTERFACE_NAME</span><span style="color: #859900;">=</span><span style="color: #268BD2;">wg0</span></span> <span class="giallo-l"><span style="color: #268BD2;">uci</span><span style="color: #2AA198;"> add_list firewall.lan.network="</span><span style="color: #859900;">${</span><span style="color: #268BD2;">WG_INTERFACE_NAME</span><span style="color: #859900;">}</span><span style="color: #2AA198;">"</span></span></code></pre><h2 id="ip-forwarding"><a class="zola-anchor" href="#ip-forwarding" aria-label="Anchor link for: ip-forwarding">🔗</a> IP Forwarding</h2> <p>The most crucial step for this setup is to enable IP forwarding on the VPS host. This forwards the packets received from the 192.168.1.0/24 clients back to the connected peer with Wireguard handling the routing based on our <code>AllowedIPs</code> config.</p> <pre class="giallo" style="color: #657B83; background-color: #FDF6E3;" ><code data-lang="plain"><span class="giallo-l"><span># /etc/sysctl.conf</span></span> <span class="giallo-l"><span>net.ipv4.ip_forward=1</span></span></code></pre> <p>Reboot the VPS for this to take effect.</p> <p>You should now be able to access your home router and clients over the public internet!</p>Liked this article? Share this with others
Got any questions or comments? Drop me a message on Twitter @shalzzj
Sign up for my newsletter to be the first to know about a new post