Access a Tailscale network from iOS with MintFlow Route via VPN
Use MintFlow NetStack's free WireGuard and Route via VPN features to reach a Tailscale tailnet through a SOCKS5 proxy, with an iptables SNAT alternative for Linux gateways.
MintFlow NetStack can route selected traffic through an HTTP or SOCKS proxy, and that proxy can itself be reached over a WireGuard peer. This makes it possible to access a Tailscale network from iOS without installing a separate Tailscale client on the phone.
The useful part is that this setup only needs MintFlow’s free networking features:
- a WireGuard interface and peer in MintFlow;
- a SOCKS5 proxy reachable over that WireGuard link;
- Route via VPN enabled on that proxy;
- a route for the Tailscale CGNAT range,
100.64.0.0/10, pointing to the proxy.
Topology
The gateway server joins two networks:
- the WireGuard network between MintFlow and the server, for example
10.7.0.0/24; - the Tailscale network, where nodes normally use addresses from
100.64.0.0/10.
MintFlow sends traffic for 100.64.0.0/10 to a SOCKS5 proxy on the server’s WireGuard address. The proxy then sends the traffic into the tailnet.
For example:
iPhone / MintFlow
WireGuard IP: 10.7.0.2
|
| WireGuard
v
Linux gateway
WireGuard IP: 10.7.0.1
tailscaled userspace SOCKS5: 10.7.0.1:1055
|
v
Tailscale tailnet
Routes: 100.64.0.0/10
Method 1: tailscaled userspace SOCKS5
This method is the simplest because the gateway does not need to forward packets at the Linux kernel layer. Tailscale documents userspace networking mode with a SOCKS5 server for environments where a normal TUN device is not available, and the same mode works well as a bridge for MintFlow’s Route via VPN feature.
On the Linux gateway, bring up WireGuard first. The exact WireGuard configuration depends on your server, but the server side usually looks like this:
[Interface]
Address = 10.7.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
[Peer]
PublicKey = IPHONE_PUBLIC_KEY
AllowedIPs = 10.7.0.2/32
Then start tailscaled in userspace networking mode and bind the SOCKS5 listener to the WireGuard address.
Use a separate state directory and Unix control socket so this gateway instance does not conflict with the default system Tailscale daemon:
sudo mkdir -p /var/lib/tailscale-mintflow /run/tailscale-mintflow
sudo tailscaled \
--tun=userspace-networking \
--socks5-server=10.7.0.1:1055 \
--state=/var/lib/tailscale-mintflow/tailscaled.state \
--socket=/run/tailscale-mintflow/tailscaled.sock
In another shell, authenticate the gateway into your tailnet:
sudo tailscale --socket=/run/tailscale-mintflow/tailscaled.sock up
If you prefer a systemd service, put the same tailscaled flags into an override for your Tailscale daemon, or run a separate service dedicated to this gateway role.
In MintFlow NetStack:
- Add a WireGuard interface that connects to the gateway.
- Add the WireGuard peer and routing rules needed to reach the gateway’s WireGuard IP, such as
10.7.0.1/32. - Add a SOCKS5 proxy with server
10.7.0.1and port1055. - Enable Route via VPN on that SOCKS5 proxy.
- Add a route for
100.64.0.0/10and point it to the SOCKS5 proxy.
After that, connections from iOS to Tailscale IPs such as 100.x.y.z go through MintFlow, over WireGuard to the gateway, then through the userspace Tailscale SOCKS5 server into the tailnet.
Method 2: normal Tailscale client with Linux SNAT
You can also run the regular Tailscale client on the gateway and let Linux forward packets between WireGuard and tailscale0. In this mode MintFlow does not need a SOCKS5 proxy. It sends 100.64.0.0/10 over the WireGuard tunnel and the gateway uses kernel routing plus SNAT.
Install and authenticate Tailscale normally:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Enable IPv4 forwarding:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-mintflow-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-mintflow-tailscale.conf
Add forwarding and masquerade rules. Replace wg0 with your WireGuard interface name if different:
sudo iptables -A FORWARD -i wg0 -o tailscale0 -d 100.64.0.0/10 -j ACCEPT
sudo iptables -A FORWARD -i tailscale0 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.7.0.0/24 -d 100.64.0.0/10 -o tailscale0 -j MASQUERADE
With nftables, the same idea is:
sudo nft add table inet mintflow
sudo nft add chain inet mintflow forward '{ type filter hook forward priority 0; policy drop; }'
sudo nft add rule inet mintflow forward iifname "wg0" oifname "tailscale0" ip daddr 100.64.0.0/10 accept
sudo nft add rule inet mintflow forward iifname "tailscale0" oifname "wg0" ct state established,related accept
sudo nft add table ip mintflow_nat
sudo nft add chain ip mintflow_nat postrouting '{ type nat hook postrouting priority 100; policy accept; }'
sudo nft add rule ip mintflow_nat postrouting ip saddr 10.7.0.0/24 ip daddr 100.64.0.0/10 oifname "tailscale0" masquerade
In MintFlow NetStack, configure the WireGuard peer and route 100.64.0.0/10 directly through the WireGuard peer instead of through a SOCKS5 proxy.
Which method should you choose?
Use the userspace SOCKS5 method if you want a minimal gateway and want to keep the route control inside MintFlow’s proxy routing model. It is also a good fit when you only need TCP-style application access through a SOCKS5 proxy.
Use the regular Tailscale plus SNAT method if you want packet forwarding at the gateway and do not want to expose a SOCKS5 service. This is closer to a traditional router setup, but it requires Linux forwarding and firewall/NAT rules.
Notes
- Bind the SOCKS5 listener to the WireGuard address, not to a public interface.
- Restrict your firewall so only the WireGuard peer can reach the SOCKS5 port.
100.64.0.0/10is the Tailscale IPv4 address range. If you also need access to advertised subnet routes, add those destination prefixes in MintFlow too.- If MagicDNS names are required, configure DNS carefully. Routing raw Tailscale IPs is simpler than routing names.
References: