A home WireGuard tunnel can give a laptop on a hotel or coffee-shop network a route back to your own services and send its internet traffic out through your home connection. The encrypted part runs between your device and your WireGuard endpoint. After packets leave home, ordinary internet security still matters; the tunnel does not make every website private or make a public network trustworthy. Captive portals may also require you to sign in before the tunnel can connect.
This guide builds a road-warrior client for a Linux server at home. The first working path is an IPv4 default route. A dual-stack client needs an IPv6 path as well before anyone can honestly call it an all-traffic tunnel. I’ll show the extra routing checks and where to stop if your home network cannot support them. The goal is a connection you can test, not an impressive-looking configuration file.
Plan the route before generating keys
You need a Linux host with WireGuard, a way to reach it from outside, and a router that forwards your chosen UDP port to it. WireGuard’s installation page lists packages and apps for Linux, Windows, macOS, iOS, and Android. The examples below use Ubuntu or Debian commands and UDP 51820; another port can work if both ends and the router agree.
If your home IPv4 address changes, use a dynamic DNS name and verify that it currently resolves to your home connection. If your provider puts you behind carrier-grade NAT, an ordinary inbound IPv4 port forward may not be reachable; you need another reachable endpoint or a separate relay design. Do not spend an hour editing keys when the first missing piece is an inbound path.
Choose a tunnel subnet that does not overlap with your home LAN or the networks your client is likely to visit. This example uses 10.77.42.0/24, with 10.77.42.1 for the server and 10.77.42.2 for the laptop. Replace it if it collides with anything you already route. An overlap can send home-bound traffic to the wrong local interface. Ubuntu’s peer-to-site guide likewise gives the tunnel its own subnet and distinguishes it from the home LAN.
Create the server and protect its keys
Install WireGuard on the Linux host:
sudo apt update
sudo apt install wireguard
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key; wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.key
WireGuard’s quick start sets umask 077 before creating private keys. The private file must stay private; the .pub file is what you share with peers. The commands above create the keys in the root-owned WireGuard directory instead of leaving a private key in your shell’s working directory. If you use a different path, keep the same restrictive permissions.
Create /etc/wireguard/wg0.conf as root and set its mode to 0600. Replace eth0 with the interface that carries the server’s route toward the internet; check ip route get 1.1.1.1. These example rules use the iptables command family. Adapt them to your existing firewall rather than layering a second policy on top of UFW or nftables without checking rule order.
[Interface]
Address = 10.77.42.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
PostUp = iptables -A FORWARD -i %i -o eth0 -s 10.77.42.0/24 -j ACCEPT; iptables -A FORWARD -i eth0 -o %i -d 10.77.42.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT; iptables -t nat -A POSTROUTING -s 10.77.42.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -o eth0 -s 10.77.42.0/24 -j ACCEPT; iptables -D FORWARD -i eth0 -o %i -d 10.77.42.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT; iptables -t nat -D POSTROUTING -s 10.77.42.0/24 -o eth0 -j MASQUERADE
sudo chmod 600 /etc/wireguard/wg0.conf
The forward rules admit traffic from the tunnel toward the upstream interface and return traffic for established connections. The NAT rule makes the tunnel’s private IPv4 addresses usable through the home host’s upstream address. Ubuntu’s default-gateway guide requires both IPv4 forwarding and masquerading for this pattern. If your home LAN uses another interface, add a specific rule for the LAN you want to reach; the internet rule above is not a blanket LAN access policy.
Enable IPv4 forwarding with a dedicated sysctl file:
printf 'net.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/70-wireguard-routing.conf
sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf
sudo sysctl net.ipv4.ip_forward
Forward UDP 51820 from the router to this host and permit that port in the host’s input firewall. With UFW, sudo ufw allow 51820/udp opens the listening port, but forwarding needs its own routed policy. Do not change DEFAULT_FORWARD_POLICY to ACCEPT just to make one VPN work. If UFW owns forwarding, use a scoped ufw route allow rule for the tunnel subnet and upstream interface, and arrange NAT in UFW’s supported ruleset. Ubuntu’s firewall guide explains the NAT and forwarding pieces.
Start the interface and check it:
sudo systemctl enable --now wg-quick@wg0
sudo wg show
No peer appears yet because we have not added one. That is expected.
Give each client a separate identity
Generate the laptop’s key pair on the laptop, with restrictive file creation permissions. On Linux:
umask 077
wg genkey > laptop.key
wg pubkey < laptop.key > laptop.pub
Do not send laptop.key to the server. Put the contents of laptop.pub into a peer section in the server’s wg0.conf:
[Peer]
PublicKey = <contents of laptop.pub>
AllowedIPs = 10.77.42.2/32
Here AllowedIPs associates the laptop’s key with its one tunnel address. It also constrains which source address the server accepts from that peer, as Ubuntu’s WireGuard peer guide explains. Give each additional client a separate key pair and a distinct /32. Restart wg-quick@wg0 after editing the server file, or use a deliberate live configuration update if you know how to preserve it.
Create a client config. The DNS target must be a resolver that actually exists and answers; 10.77.42.1 would be wrong unless you installed and exposed DNS there. This Linux example uses systemd-resolved to select a public resolver, 1.1.1.1, reached over the home IPv4 route. Replace it with a reachable home resolver if you need local hostnames. The resolver you choose can see your DNS questions, and Ubuntu documents DNS selection as a separate part of a default-gateway VPN.
[Interface]
Address = 10.77.42.2/32
PrivateKey = <contents of laptop.key>
PostUp = resolvectl dns %i 1.1.1.1; resolvectl domain %i '~.'
[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
Endpoint = your-verified-home-name.example:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Save the client file with mode 0600 on Linux. The wg-quick manual says 0.0.0.0/0 installs an IPv4 default route. The PostUp line follows Ubuntu’s systemd-resolved example; it assumes the resolvectl command and service are present. A phone app or another network manager may instead expose a DNS = 1.1.1.1 setting. On Linux, wg-quick itself handles a DNS line through resolvconf, which Ubuntu does not normally install by default. Test the active resolver, not just the line in the file. PersistentKeepalive = 25 is useful for a client behind NAT; it is not a requirement for every peer, and WireGuard gives 25 seconds as a sensible interval.
IPv6 is a separate routing decision
The sample above routes IPv4 only. A dual-stack client can still use its ordinary IPv6 path outside this tunnel. Do not add ::/0 to the client and call it fixed: the server also needs a tunnel IPv6 address, a unique address for each peer, IPv6 forwarding, an IPv6 route toward the internet, firewall rules, and a return path. If your host gets its upstream IPv6 default route from router advertisements, enabling IPv6 forwarding may stop it accepting those advertisements unless accept_ra=2 is set for that upstream interface; the Linux kernel documents this behavior.
For a genuine dual-stack design, use a routed IPv6 prefix delegated to the tunnel where possible, or explicitly design IPv6 NAT and filtering if that is how your home connection works. Put the server and client IPv6 tunnel addresses in their [Interface] sections, the client’s unique /128 in the server peer’s AllowedIPs, and ::/0 alongside 0.0.0.0/0 in the client peer only after the server can forward and return IPv6 traffic. Test IPv6 reachability and the visible IPv6 egress address from an outside network. If you cannot provide and verify that path, treat this guide as an IPv4 tunnel and do not claim that it routes all client traffic. A separate client policy that prevents ordinary IPv6 egress while connected is another option, but it must be configured and tested for that operating system.
Verify the route, DNS, and failure behavior
Connect from a network outside your home. A captive portal may need its login first. Then check the server’s sudo wg show for a recent handshake and increasing transfer counters. On a Linux laptop, ip -4 route alone can be misleading because wg-quick may use policy routing for a default tunnel; inspect ip -4 rule and the interface state as well. Ubuntu’s default-gateway walkthrough demonstrates that distinction.
Check an IPv4 address-echo service before and after connecting: the connected result should match your home egress IPv4, not the hotel’s. Resolve a domain and inspect which DNS server the client is actually using. If you use 1.1.1.1, the home exit path carries the query to that resolver; it is not your private home DNS. If you configured a home resolver, test a local name as well as a public one. Finally, test IPv6 separately. If it succeeds outside the tunnel, you have an IPv6 escape path. If it fails, you have blocked IPv6 rather than routed it; describe that accurately.
Troubleshoot in order. No handshake? Check the endpoint name, port forward, host firewall, and whether packets reach UDP 51820 with tcpdump. Handshake but no internet? Check net.ipv4.ip_forward, the forward chain, NAT, and the server’s upstream route. Internet by IP but not by name? Check the chosen resolver and the client OS’s DNS integration. Home LAN unreachable? Add only the needed LAN route/firewall permission and verify that its subnet does not overlap the visited network. If the tunnel works but calls lag while the home upload is busy, check that connection's capacity and queueing; our OpenWrt CAKE guide covers one router-side approach. Keep the question narrow: a successful handshake proves keys and transport, not DNS or forwarding.
Back up the server’s private keys and configs in an encrypted, access-controlled location, and protect client configs because they contain private keys too. A lost client device should have its peer removed from the server. Keep the server OS and WireGuard tools updated, and check that your dynamic DNS name still points to a reachable endpoint. These are ordinary operations tasks; none is solved by the tunnel protocol itself.
WireGuard gives you an encrypted route to home. What happens after that depends on the DNS server, the home gateway, the destination service, and whether both IP families really follow the plan. Start with one client and prove the path before adding the rest. Vendor marketing can wait until the packet capture agrees.