Hi, so been working on this for a week but not really happy with the solutions I find as they seem to be done by induviduals who rely heavily on ai. I got wireguard easy going and can remotly connect which is great but id love to be able to route any internet traffic to and from the wireguard clients to go though another server while filtering my local onsite services. Felt that if i can crack this i dont need to rely on tailscale. The end goal is to have no reliance on tailscale as i am preparing for the eventual enshitification.
Have a look at self hosted netbird on a VPS. Its free and has very little feature restrictions https://netbird.io/
I will tomorrow :) originally i was thinking about it then i got all caught up with wg-easy. Its looked promising when i first looked but it had one or two cavietes that made me decide against it. Will definantly revisit thanks for the suggestion!
I’ve started working on something very similar ( Client -> Wireguard -> homeserver -> Mullvad -> Internet), but didn’t get too far and saved the project for later. IIRC, I had issues defining more clearly in the post-up / post-down hooks which traffic was supposed to go where. Upon bringing up the tunnel to Mullvad, I’d lose SSH access instantaneously. I’ll watch this thread closely and contribute once I get around to tackle the issue sometime this summer.
Yes! Thats the issue im having. I can make wireguard clients connect to mullvad and work but once i try to split tunnel through the post up down hooks i get stuck. Glad im not alone there. The conversations here i wonder if there is an issue with (if your using gluetun) iptables and the wireguard easy nftables. But yes so glad im not alone here with the weird fuckery :-) ill be honest im prob going to try a spin up headscale. Looking online it seems like its the most mature answer and the roads well worn. Just feel its might burn more resources than this would.
Acronyms, initialisms, abbreviations, contractions, and other phrases which expand to something larger, that I’ve seen in this thread:
Fewer Letters More Letters DNS Domain Name Service/System ISP Internet Service Provider NAT Network Address Translation SSH Secure Shell for remote terminal access Unifi Ubiquiti WiFi hardware brand VPN Virtual Private Network VPS Virtual Private Server (opposed to shared hosting)
[Thread #14 for this comm, first seen 15th Jun 2026, 11:10] [FAQ] [Full list] [Contact] [Source code]
I have a custom made ansible role that does what you are asking for. I’ve wanted to clean it up a bit before putting it up on Github, and your post just gave me a motivation to stop procrastinating it :) This was initially made for my own use, and I’m not an Ansible expert so it can have some rough edges, but I tried my best to make it adhere to the Ansible way of doing things (applying the same role to a host twice should be idempotent).
Using this role, I’m able to quickly define wireguard networks, define which peer participates in which network, optionally configure a peer as a router (with NAT and port forwarding) for a given network. For Ansible-managed hosts, it installs wireguard, generates and deploys wireguard configurations, and enables IP forwarding on exit nodes. It can also generate ready-to-deploy wireguard configurations for externally managed hosts.
The repo is at https://github.com/pcouy/ansible-wireguard . I tried giving some instructions in the readme but they may not be detailed enough. If you try it, please open an issue for anything that’s not clear enough from the readme so I can improve it. (I tried making a “Quick start” section for people who never used ansible before)
Thank you so much! I shall head over and have a look :D
Quick question (love your solution btw so eloquent could follow along easily which was such a nice change from the week i have had) does your solution manage multiple clients with different firewall requirements? Why i was heading down the wireguard ui route was the ease of firewall configuration per client. Its a weird thing where i feel headscale is a little bit more than i need and wireguard vanilla is a little too simplistic. I know nothing about ansible other than what i quickly read up on now.
Do you have specific examples of the “different firewall requirements” ?
Its via gui but its basically just server side allow list so the client cant modify the ips it can access. The ips i use for https internet are 0.0.0.0/0:443 for example
The ansible role I made does not cover this. If you make a server an exit node for a network, the server gets configured to forward everything that comes from the wireguard network. Since my use case does not need this, I don’t think I’ll add it, but the role could be expanded to support ACLs by taking inspiration from how it deals with port forwarding.
Thats ok, thanks for the idea and sharing your project! Glad to hear this post was the push that convinced you to share it with the wider world its a cool project :)
You could use headscale. Its the heart of tailscale but in an open source format.
Head scale is actually a simpler implementation rather than the heart of what tailscale uses directly. It is perfectly complete for a single persons homelab application IMHO. Would be easy for the community to maintain a fork, but its also good to see other approaches that solve the same problem.
I did consider it. But then im still using tailscale ecosystem which as much as i want to they are still an american company.
Just a bit of a nitpik, but tailscale is a Canadian company.
Well. That changes everything :D i shall look more seriously into this then. Would still love anythoughts on iptable routing tho >.<
iptables is deprecated… If you really do want to do your own custom thing you should learn nftables.
Thats probably where im having the issue then thanks for the heads up.
iptables should still work, but these days it gets converted to nftables so you may as well just learn nftables.
Having said that, I find it a pain to manually configure iptables or nftables. There might be a better way to do what you want.
Ahh good so im not just me its actually a bit of a headache. The more i talk to folk the more i feel headscales orobably going to be the way. And rely on folk smarter than i to implement the nftables. Atm im kinda doing a hamfisted approach as the two programs i am using 1 uses nftables and thebother iptables so im already making it hard for myself. Thanks so much this is the kind of clarity i was seeking.
The end goal is to have no reliance on tailscale as i am preparing for the eventual enshitification.
Tailscale is mostly open-source. If they do anything bad then someone could fork the project. The coordination server isn’t open-source, but you could self-host Headscale as a replacement.
If it still doesn’t suit your use cases, there’s some alternatives.
I personally wouldn’t directly deal with iptables or nftables rules, and instead use some other software to deal with that.
What router do you have?
For example with a Unifi router you can quite easily create a routing for that.
Im picking up what your putting down tho. Be so much easier if i could have a vpn service on a dedicated vlan then just link through with some wg configs but annoyingly my router puts wireguard ontop of the entire topography and messes up everything else.
I know this don’t the solution you are looking for, but your router sounds like the crappy default one you get from your ISP.
In that case (since you already got this far) consider getting a better one, if not for this, then for the next time it limits your adventures.
I would suggest looking into OpenWrt if you go this route.
It definantly isnt a default isp router. And openwrt doesnt support the chip i have in my router as its a tplink enterprise router. I emailed them and they said they will look into implementing it into their omada ecosystem. Unifi dont really excite me anyway they have one hell of a cve and have to answer to the signal directive. Every issue with tp link has been. You need to have acces to the router physically to implement.
Every issue with tp link has been. You need to have acces to the router physically to implement.
Come on, this is not true and you know it. Finding a counterexample was easy:
https://www.anavem.com/en/news/cybersecurity/tp-link-patches-critical-router-flaws-enabling-rce
Auth bypass + auth rce flaw. Literal remote code execution, instant own.
The problem with network appliances/routers is that they all have web ui’s, and management api’s or something of the sort. Web UI’s are extremely complex services, with lots of difficult to secure attack surface. In a router, that attack surface is now running as root (because it has to be, to manage linux (or freebsd, routers are usually based on one of the two) kernel routing and networking.
So literally every single network appliance and router has had it’s own critical vulnerabilities, even open source ones like openwrt.
The real solution here is to recognize that web interfaces are a security nightmare, and to either disable them or lock them behind ssh.
(Open)ssh, is known for having extremely few vulnerabilities, only 2.5 critical ones over it’s 25+ years of existence. That’s a big difference compared to some of these network appliances/routers which have 2+ critical vulns every quarter.
Yeah only if you enable their cloud api and dont randomise your web interface port. Both of which i do. I have also pen tested my router remotley. Also i have a router not a router wifi combo. Its not an isp or consumer router. Router splits to poe switcher and a wifi ap puck.
randomise your web interface port
Randomized interface ports change nothing except for stopping automated scanners. They don’t really help. Just lock it behind ssh, physical access or similar, and then never worry about it again.
Yeah only if you enable their cloud api
No, all of the local web interfaces have had problems too. Literally every router or network appliance has had similar issues.
ts not an isp or consumer router
ISP, consumer, and enterprise routers have all the same issues due to the same architecture. All of them.
have also pen tested my router remotley.
Me too. But it’s just not about my router being secure today, it’s about it being secure tomorrow. I want to be able to rest easy knowing that if a new vulnerability appears in xyz component then I don’t have to worry about it.
Without knowing my infrastructure your making some really impreasive assumptions buddy. If this is your day job i recommend a career change
My router doesnt allow that.
Here is the compose and post up im working on
services: gluetun: image: qmcgaw/gluetun:v3 hostname: gluetun restart: always networks: wg: ipv4_address: 192.168.1.10 ports: - 51720:51720/udp # wireguard ui - 51821:51821 # wireguard tunnel cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun environment: - VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER} - VPN_TYPE=${VPN_TYPE} - WIREGUARD_PRIVATE_KEY=${PRIVATE_KEY} - WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES} - SERVER_CITIES=${SERVER_CITIES} - ALLOWED_IPS=0.0.0.0/1 - FIREWALL_OUTBOUND_SUBNETS=${OUTBOUND_SUBNET} #change to appropriate subnet - DNS_ADDRESS=${DNS} # - HEALTH_TARGET_ADDRESS=cloudflare.com:80 # - HEALTH_VPN_DURATION_INITIAL=120s wg-easy: environment: - INSECURE=true #INITIAL SETUP NOT FOR PRODUCTION image: ghcr.io/wg-easy/wg-easy:15 container_name: wg-easy restart: unless-stopped networks: wg: ipv4_address: 192.168.1.20 volumes: - ./data:/etc/wireguard - /lib/modules:/lib/modules:ro ports: - 51720:51720/udp #wireguard - 51821:51821/tcp #web ui cap_add: - NET_ADMIN - SYS_MODULE sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 - net.ipv6.conf.all.disable_ipv6=0 - net.ipv6.conf.all.forwarding=1 - net.ipv6.conf.default.forwarding=1 networks: vpn: driver: bridge enable_ipv6: false ipam: driver: default config: - subnet: 192.168.1.0/24 #container ipgateway # - subnet: fdcc:ad94:bacf:61a3::/64Post up
# Detect the VPN bridge interface by wg-easy's container IP VPN=$(ip -o -4 addr show | awk '$4 ~ /^192.168.1.20\// {print $2; exit}'); test -n "$VPN"; iptables -P FORWARD DROP; ip6tables -P FORWARD DROP; iptables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; # Direct subnets: ip route -A 10.1.0.0/16 via 192.168.1.0/24 dev $VPN table 200; ip -6 route -A 10.1.0.0/16 via 192.168.1.0/24 dev $VPN table 200;


