WireGuard Made Clear: Server IP, Peer IP, AllowedIPs, Split-Tunnel vs Full-Tunnel (with wg-easy & CLI)
What you usually want
- Addressing plan (example):
- VPN IPv4 subnet:
10.8.0.0/24→ server =10.8.0.1, clients =10.8.0.2+ - VPN IPv6 subnet (optional):
fdcc:ad94:bacf:61a4::/64
- VPN IPv4 subnet:
- wg-easy “Server Allowed IPs” for each peer: the peer’s single address, e.g.
10.8.0.5/32andfdcc:…:cafe:5/128. - Client “AllowedIPs”:
- Split-tunnel (recommended):
10.8.0.0/24(andfdcc:…/64if using IPv6). - Full-tunnel:
0.0.0.0/0, ::/0and enable IPv4/IPv6 forwarding + NAT on the server.
- Split-tunnel (recommended):
Windows can’t be pinged? Enable firewall ICMP echo-reply rules and mark the WireGuard network as Private.
Web dies after connecting? You routed IPv6 globally (::/0) without IPv6 NAT/forwarding or DNS/MTU is wrong. Use split-tunnel or fix NAT/MTU.1) Concepts you must know (in plain English)
- Server vs. Peer: In WireGuard every node is a peer. We call the machine that accepts inbound connections the server.
- Interface Address (“Address”): The IP your peer owns inside the VPN.
Example: server10.8.0.1, Windows10.8.0.5, Raspberry Pi10.8.0.4. - AllowedIPs (client side): What destinations should be sent into the tunnel.
10.8.0.0/24→ only reach other VPN members (split-tunnel).0.0.0.0/0, ::/0→ send everything via VPN (full-tunnel).
- Server Allowed IPs (server side, wg-easy term): Which addresses belong to this specific peer.
Use single-host routes/32(IPv4) and/128(IPv6), e.g.10.8.0.5/32. - Endpoint: Where a peer dials to (public IP:port of server).
- PersistentKeepalive: Send a small packet every N seconds (usually 25) to keep NAT bindings alive.
- Split-tunnel vs Full-tunnel: Split only routes VPN subnets; full routes all traffic via server.
- DNS: If you push a DNS server (like
10.8.0.1), that server must actually answer DNS queries.
2) Pick an addressing plan (recommended defaults)
IPv4 VPN: 10.8.0.0/24
Server: 10.8.0.1
Raspberry Pi: 10.8.0.4
Windows: 10.8.0.5
IPv6 VPN (optional): fdcc:ad94:bacf:61a4::/64
Server: fdcc:...::cafe:1
Raspberry Pi: fdcc:...::cafe:4
Windows: fdcc:...::cafe:5
Use your own fd** prefix if you like; it’s just Unique Local Addressing.
3) Server setup (two ways)
3.1 Using wg-easy (Docker)
wg-easy UI fields you’ll see when creating a peer (client):
- Address (IPv4/IPv6): the peer’s interface IPs (e.g.,
10.8.0.5andfdcc:…::cafe:5). - Allowed IPs: what this peer will route into the tunnel (client-side routes distributed via the config).
- Split-tunnel:
10.8.0.0/24(+fdcc:…/64if using v6) - Full-tunnel:
0.0.0.0/0, ::/0
- Split-tunnel:
- Server Allowed IPs: single-address routes that identify this peer on the server:
10.8.0.5/32, fdcc:…::cafe:5/128 - Advanced → PersistentKeepalive:
25 - Global setting: “Allow clients to communicate with each other” → ON if you want peer-to-peer traffic.
For each peer, “Server Allowed IPs” should always be that peer’s /32 and /128—not the whole subnet.
3.2 Using raw wg/wg-quick (CLI)
/etc/wireguard/wg0.conf (server)
[Interface]
Address = 10.8.0.1/24, fdcc:ad94:bacf:61a4::cafe:1/64
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# Optional DNS for local clients if you run a resolver at 10.8.0.1
# PostUp/PostDown: NAT + firewall rules are added in Section 6
# Raspberry Pi
[Peer]
PublicKey = <PI_PUBLIC_KEY>
AllowedIPs = 10.8.0.4/32, fdcc:ad94:bacf:61a4::cafe:4/128
PersistentKeepalive = 25
# Windows laptop
[Peer]
PublicKey = <WIN_PUBLIC_KEY>
AllowedIPs = 10.8.0.5/32, fdcc:ad94:bacf:61a4::cafe:5/128
PersistentKeepalive = 25
4) Client configs
4.1 Windows (WireGuard GUI)
Split-tunnel (recommended):
[Interface]
PrivateKey = <WIN_PRIVATE_KEY>
Address = 10.8.0.5/24, fdcc:ad94:bacf:61a4::cafe:5/112
DNS = 1.1.1.1, 2606:4700:4700::1111 # or omit; see Section 5
MTU = 1420 # try 1280 if you have page loading issues
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP>:51820
AllowedIPs = 10.8.0.0/24, fdcc:ad94:bacf:61a4::/64
PersistentKeepalive = 25
Full-tunnel:
AllowedIPs = 0.0.0.0/0, ::/0
If you choose full-tunnel, you must enable forwarding + NAT on the server (Section 6).
Make Windows ping-friendly (ICMP + Private profile)
Open Administrator PowerShell:
# Mark WireGuard network as Private
Get-NetConnectionProfile | ? {$_.InterfaceAlias -like "WireGuard*"} |
Set-NetConnectionProfile -NetworkCategory Private
# Allow inbound ping (ICMP Echo) for IPv4 & IPv6
Get-NetFirewallRule -DisplayName "*Echo Request*" -Direction Inbound | Enable-NetFirewallRule
# (Or enable in "Advanced Security" under "File and Printer Sharing (Echo Request - ICMPv4-In)".)
4.2 Raspberry Pi / Linux client
/etc/wireguard/wg0.conf
[Interface]
PrivateKey = <PI_PRIVATE_KEY>
Address = 10.8.0.4/24, fdcc:ad94:bacf:61a4::cafe:4/112
DNS = 1.1.1.1 # optional; see Section 5
MTU = 1420 # try 1280 if issues
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP>:51820
AllowedIPs = 10.8.0.0/24, fdcc:ad94:bacf:61a4::/64
PersistentKeepalive = 25
Bring it up:
sudo apt update && sudo apt install -y wireguard resolvconf
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
5) DNS: three safe patterns
- Use public DNS locally (simplest): set
DNS = 1.1.1.1(and/or8.8.8.8). - Push your own DNS from the VPN (e.g.,
10.8.0.1) only if the server is actually running a resolver. - For split-tunnel, you can omit
DNS=entirely to keep your local resolver.
Symptom of bad DNS: websites don’t resolve (but pinging an IP works). Check nslookup example.com after connecting.
6) Full-tunnel requires forwarding + NAT on the server
If any client uses AllowedIPs = 0.0.0.0/0 (and/or ::/0), the server must behave like a router.
Enable kernel forwarding (Debian/Ubuntu):
sudo tee /etc/sysctl.d/99-wg.conf >/dev/null <<'EOF'
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
sudo sysctl --system
Add NAT (nftables). Replace eth0 with your server’s internet interface:
sudo nft add table inet nat
sudo nft 'add chain inet nat postrouting { type nat hook postrouting priority 100 ; }'
sudo nft add rule inet nat postrouting oif "eth0" ip saddr 10.8.0.0/24 masquerade
# If you really route IPv6 globally, also add:
sudo nft add rule inet nat postrouting oif "eth0" ip6 saddr fdcc:ad94:bacf:61a4::/64 masquerade
Many people break the web by enabling::/0on the client without IPv6 NAT/forwarding on the server. If you don’t need full-tunnel IPv6, prefer split-tunnel (fdcc:…/64) and skip IPv6 NAT.
7) MTU / MSS problems (why some pages hang)
If pages partially load or some sites fail, try lower MTU = 1280 on both client and server WG interfaces.
(You can also clamp MSS in your firewall, but MTU 1280 is the quick fix.)
8) End-to-end test checklist (copy-paste)
On each client after connecting:
# Linux/macOS:
wg show
ip a show wg0
ping -c 3 10.8.0.1 # ping server inside VPN
# Split-tunnel should keep your default route local:
ip route get 1.1.1.1
# (Windows) PowerShell:
# tracert -4 1.1.1.1
# tracert -6 2606:4700:4700::1111
# nslookup aicargo.pro
If you expect full-tunnel:
curl -4 https://ifconfig.co
curl -6 https://ifconfig.co
# Should show the server’s public IPs.
Windows ↔ Raspberry Pi ping:
- Ensure Windows ICMP inbound rules are enabled (Section 4.1).
From Raspberry Pi:
ping -c 3 10.8.0.5
traceroute 10.8.0.5
9) Common pitfalls (and quick fixes)
- Can’t ping Windows: Windows firewall blocks ICMP or WG network is “Public”. → Set to Private + enable Echo Request rules.
- VPN connects, web dies: You routed IPv6 globally (
::/0) but server lacks IPv6 NAT/forwarding. → Use split-tunnel or add IPv6 NAT. - Handshake OK, no traffic:
Server Allowed IPsnot set to/32(and/128) per peer, or “clients can talk to each other” is off. - Permission denied (SSH): Wrong user/key, or
~/.sshpermissions wrong (700 dir, 600authorized_keys), or serversshdnot listening onwg0. - Multiple peers use the same IP: Each peer must have a unique
Address. - DNS broken: You pushed a VPN DNS that doesn’t answer. Use 1.1.1.1/8.8.8.8 or run a real resolver on the server.
- MTU blackhole: Drop MTU to 1280.
10) Minimal reference configs
Server (wg-easy conceptually):
- Peer “Windows”
- Address:
10.8.0.5(andfdcc:…::cafe:5) - Allowed IPs:
10.8.0.0/24(+fdcc:…/64) - Server Allowed IPs:
10.8.0.5/32(+fdcc:…::cafe:5/128) - PersistentKeepalive:
25
- Address:
- Peer “RaspberryPi”
- Address:
10.8.0.4(andfdcc:…::cafe:4) - Allowed IPs:
10.8.0.0/24(+fdcc:…/64) - Server Allowed IPs:
10.8.0.4/32(+fdcc:…::cafe:4/128) - PersistentKeepalive:
25
- Address:
- Global: “Clients can communicate” → ON
Windows (split-tunnel):
[Interface]
PrivateKey = <WIN_KEY>
Address = 10.8.0.5/24, fdcc:ad94:bacf:61a4::cafe:5/112
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = <SERVER_KEY>
Endpoint = <SERVER_IP>:51820
AllowedIPs = 10.8.0.0/24, fdcc:ad94:bacf:61a4::/64
PersistentKeepalive = 25
Raspberry Pi (split-tunnel):
[Interface]
PrivateKey = <PI_KEY>
Address = 10.8.0.4/24, fdcc:ad94:bacf:61a4::cafe:4/112
DNS = 1.1.1.1
MTU = 1420
[Peer]
PublicKey = <SERVER_KEY>
Endpoint = <SERVER_IP>:51820
AllowedIPs = 10.8.0.0/24, fdcc:ad94:bacf:61a4::/64
PersistentKeepalive = 25
11) FAQ
Q: Which side sets what?
- Client “AllowedIPs”: what the client sends into the tunnel.
- Server “Server Allowed IPs”: which addresses identify that client (routing back).
Q: Do I need IPv6?
No. If you don’t need it, skip it entirely. If you use it, prefer split-tunnel (/64) unless you also configure IPv6 NAT/forwarding for full-tunnel.
Q: Why use /32 on the server for a peer?
So the server knows “packets for 10.8.0.5 must go to that peer.” Using a wide subnet there breaks routing between peers.
Q: DNS via VPN or not?
If your server doesn’t run a resolver, don’t push DNS=10.8.0.1. Use public resolvers or run Unbound/AdGuard on the server.
12) Troubleshooting: single-command pack
# On server
sudo wg show
sudo nft list ruleset | sed -n '1,160p'
ip route
ip -6 route
# On Linux client
wg show
ip a show wg0
ip route get 1.1.1.1
ping -c 3 10.8.0.1
curl -4 https://ifconfig.co
# On Windows (PowerShell)
tracert -4 1.1.1.1
tracert -6 2606:4700:4700::1111
nslookup example.com
Get-NetConnectionProfile | ? {$_.InterfaceAlias -like "WireGuard*"}
Get-NetFirewallRule -DisplayName "*Echo Request*" -Direction Inbound
Final note
If your goal is peer-to-peer inside the VPN (Windows ↔ Raspberry Pi), the safest recipe is:
- Split-tunnel on both clients (
AllowedIPs = 10.8.0.0/24). - On the server, Server Allowed IPs = each peer’s /32 (and /128).
- Enable “clients can communicate with each other.”
- On Windows, set WireGuard network to Private and enable Echo Request rules.
That combination “just works” and won’t break your normal web browsing.

这两个是 wg-easy 里给“某个客户端(peer)” 填的两处,作用不一样:
1) Allowed IPs(客户端要走隧道的“目的地”)
- 这是客户端的路由表:哪些目的地址要丢进 WireGuard 隧道。
- 常见填法:
- 只想访问 VPN 内网:
10.8.0.0/24(只走到 WG 虚拟网段,不走公网) - 全量代理(所有流量都走 VPN):
0.0.0.0/0, ::/0 - 只带公司网段:
192.168.1.0/24(只这段走隧道,其它直连)
- 只想访问 VPN 内网:
你图里 10.8.0.0/24 的意思:客户端只把去 10.8.0.x 的包交给 VPN,其它网站不会走 VPN。2) Server Allowed IPs(服务器认为“这个客户端拥有/负责”的地址)
- 这是服务器侧的“路由 + 白名单”:哪些源地址/网段是由这个客户端发来的、或这个客户端背后可达。
- 必须至少包含这个客户端的隧道地址/32,比如:
10.8.0.5/32(表示这台客户端“拥有”10.8.0.5) - 做站点互联时,还可加客户端后面的网段,如:
192.168.50.0/24(服务器和其它 peer 才会把这网段的流量转给它)
你图里 10.8.0.5/32 的意思:这台客户端的隧道 IP 是 10.8.0.5,服务器把发往 10.8.0.5 的包交给它;也不允许别的客户端冒用这个地址。一句话对比
- Allowed IPs(客户端):我(客户端)要把“去哪些目的地”的流量交给 VPN。
- Server Allowed IPs(服务器):这台客户端“拥有/负责”哪些 IP/网段,服务器把“去这些地址”的流量转给它,并且只接受它用这些源地址。
快速填法模板
- 单纯远程进内网:
- Allowed IPs:
10.8.0.0/24 - Server Allowed IPs:
10.8.0.X/32(X=分配给这台客户端的地址)
- Allowed IPs:
- 全局代理:
- Allowed IPs:
0.0.0.0/0, ::/0 - Server Allowed IPs:
10.8.0.X/32
- Allowed IPs:
- 站点到站点(客户端后面有局域网):
- Allowed IPs(客户端):
0.0.0.0/0或只需要的网段 - Server Allowed IPs(服务器):
10.8.0.X/32, 192.168.50.0/24
- Allowed IPs(客户端):
小坑:两台客户端的 Server Allowed IPs 不能重叠(比如都写 10.8.0.5/32 或同一私网段),否则路由冲突。