In my university, the network type can be divided into two kinds:
The access point is placed in every dormitory with four Gigabit Ethernet ports and Wi-Fi 6 wireless. However, it has two limitations:
However, using an Ethernet cable connection (but not wireless), the speed from the dormitory area to the research area (i.e. Intranet access) can be up to 100Mbps and require no authentication when establishing a connection on port 53 using UDP.
The access point, which is several Gigabit Ethernet ports on the wall, is placed in nearly every room in administration buildings or research buildings.
The external backbone is CERNET IPv4 / IPv6 dual stack and can be up to 1000Mbps speed per account.
However, IPv6 is assigned by SLAAC rather than Prefix Delegation. The host cannot be accessed from the Internet because there exists at least one stateful firewall in the path.
When I back to my home, the official tunnel provided by my uni was limited to access some services only. That is, it is a selective tunnel rather than a "proxy all" tunnel.
In case I want to access a website that is not in the proxy range, I will not be able to do that since this traffic is not routed via (more precisely, accepted by) the school tunnel.
Plus, this official tunnel is completely unable to be used when registering for the courses. I need to find another way to get into uni's Intranet to avoid the tragedy.
To summarize, the problems are as follows:
For problem 1:
Since legally I can only use my account for authentication which limits the port connection, I must find a way to establish a fast and secure tunnel on port 53 using UDP.
Plain DNS tunnel is just too slow and w/o support on multi-platform. Other tunnel protocols are too complex and too slow when compared to WireGuard.
So WireGuard is the best choice. It has the fastest speed and runs on UDP.
For problem 2:
Since there exists a stateful firewall which neither I have access to nor can bypass easily, the choices are limited to either setting up a public server served as a relay or using a "managed" virtual network.
And I don't want to pay an extra fee. So after comparison, I choose Zerotier.
After solving usability, we can consider something more. Both WireGuard and Zerotier support IPv6.
And rethink from a higher level, can I set up Zerotier to solve problem one?
The answer is no. I managed to change the default port from 9993 to 53. However, the connection quality to jumphost is very bad. I assume the reason behind this is the host discovery mechanism is not suitable in this scenario.
I use Ubuntu 24.04 LTS as the jumphost operating system.
sudo apt update && sudo apt full-upgrade sudo apt install wireguard ndppd curl -s https://install.zerotier.com | sudo bash
For mainland China readers, apart from configuring apt mirrors, you may want to replace the last command with this:
curl https://install.zerotier.com/ | sed 's,download.zerotier.com/,mirrors.ustc.edu.cn/zerotier/,g' | sudo bash
And you should always follow the official guide:
Edit /etc/sysctl.conf to add the following lines to support IPv4 & IPv6 forwarding:
net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 # And optionally, BBR congestion algorithm: net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr
Some useful commands for checking firewall status, IP address, route tables.
iptables -L iptables -L -t nat nft list ruleset ufw status ip a ip r
And we do some conventions here:
INTERNET_IF: the interface on jumphost that has Internet access and the user's device has access to it. INTERNET_IPv4 / INTERNET_IPv6: the corresponding IP of INTERNET_IF INTERNET_IPv4_RANGE / INTERNET_IPv6_RANGE: the corresponding IP range of INTERNET_IF ZT_IF: Zerotier interface on jump host ZT_IPv4 / ZT_IPv6: the corresponding IP of ZT_IF ZT_IPv4_RANGE / ZT_IPv6_RANGE: the corresponding IP range of ZT_IF WG_IF: Wireguard interface on jump host WG_IPv4 / WG_IPv6: the corresponding IP of WG_IF WG_IPv4_RANGE / WG_IPv6_RANGE: the corresponding IP range of WG_IF
The most important thing to check is the WAN_IPv6 subnet mask. As long as not an /128, we can use the NDP relay scheme. Otherwise, we can only use the IPv6 NAPT scheme. Luckily, the writer's uni distributes /64 subnet. This means the writer can customize the remaining 64 bits of network address.
We need a good IPv6 range that has the same prefix as INTERNET_IPv6, and the prefix length is a subnet mask. We can choose freely in the remaining bits. But notice that, the more bits you customize, the fewer clients you can have. e.g.
INTERNET_IPv6_RANGE: aaaa:bbbb:cccc:dddd:1111:2222:3333:4444/64
Since we have /64 masks, means our WG_IPv6_RANGE must have aaaa:bbbb:cccc:dddd as the beginning. And we like this interesting string: 0d00 0721. So:
WG_IPv6_RANGE: aaaa:bbbb:cccc:dddd:0d00:0721:0001:0/112
We fixed 0d00:0721:0001 as our WG_IPv6_RANGE's prefix and its corresponding mask is /112
Second, choose a proper IPv4 range. The writer recommends to choose within 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 with two limitations:
This is to avoid some confusion.
This is obvious I guess?
(And this is checked when using WireguardConfigGenerator written by the writer)
The writer has written a simple generator that supports IPv6.
The writer recommends that readers read official Wireguard documentation, as they provide enough background information.
Tl;dr:
{
"client_number": YOUR_CLIENT_NUMBER,
"ipv4_range": "WG_IPv4_RANGE",
"ipv6_range": "WG_IPv6_RANGE",
"preshared_key_flag": true,
"server": {
"persistent_keepalive": "",
"listen_port": "51820",
"fwmark": "",
"dns": "",
"mtu": "",
"table": "",
"preup": "",
"postup": "",
"predown": "",
"postdown": "",
"saveconfig": ""
},
"client": {
"allowed_ips": "0.0.0.0/0, ::/0",
"endpoint": "INTERNET_IPv4:51820",
"persistent_keepalive": "",
"fwmark": "",
"dns": "8.8.8.8",
"mtu": "",
"table": "",
"preup": "",
"postup": "",
"predown": "",
"postdown": "",
"saveconfig": ""
}
}
Then, put generated server.conf at jumphost's /etc/wireguard/ directory.
Last, of this sector, activate auto start on booting:
systemctl enable --now wg-quick@server
The writer recommends to use nftables over iptables and uses it. So the writer will provide nftables configuration only.
The writer's config is not optimized for security at the current time. Plus when copying and pasting this config, the reader needs to make sure ufw is disabled and iptables is clean. Be wary of these!
Edit /etc/nftables.conf
Perhaps it's better to set a proper MTU value instead of doing MSS clamping since MSS clamping only affect TCP packet.
#!/usr/sbin/nft -f
flush ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "INTERNET_IF" masquerade
}
}
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
tcp flags syn tcp option maxseg size set rt mtu
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Enable and reboot nftables service:
systemctl enable nftables systemctl restart nftables
Now if the reader is lucky, by connecting Wireguard the client is already connected to the Internet via jumphost. However, there exists a situation in which the gateway of INTERNET_IF does not handle IPv6 traffic without NDP discovery. Then we need to do NDP proxy.
The writer uses ndppd to proxy NDP. But its behaviour is a mystery. If not working, please try other options in the configuration file or switch to other NDP proxy tools. The writer cannot guarantee that it is usable and has a plan to implement NDP proxy in the future. Stay tuned.
Edit /etc/ndppd.conf
route-ttl 30000
proxy INTERNET_IF {
router yes
timeout 500
keepalive yes
rule WG_IPv6_RANGE {
static
}
}
Just the same as Part 1, but the writer recommends not assigning the same subnet for clarity.
The reader has two (actually three) choices:
The writer recommends ZeroTier 6PLANE over others because:
See:
Now, go to Settings > Advanced > IPv6 Auto-Assign. Select ZeroTier 6PLANE and unselect ZeroTier RFC4193. Then configure Auto-Assign from Range by using Set IPv6 Address Pool. Fill Range Start and Range End according to ZT_IPv6_RANGE.
Then, go to Settings > Advanced > IPv4 Auto-Assign. Set Auto-Assign Pools by filling Range Start and Range End according to ZT_IPv4_RANGE.
After that, go to Settings > Advanced > Managed Routes. Make sure that it has ZT_IPv4_RANGE (LAN) and ZT_IPv6_RANGE (LAN). If not, put ZT_IPv6_RANGE or ZT_IPv6_RANGE in Add Routes > Destination and leave Via blank to add these rules.
Now, the reader can check and change auto-assigned IPv4 and IPv6 addresses for Zerotier clients.
The last but optional step is if the reader wants a "connect and use" VPN. The reader needs to add these two routes: 0.0.0.0/0 to ZT_IPv4 and::/0 to ZT_IPv6(if using 6PLANE, set to 6PLANE IP). However, the writer's choice is to manually set it per client.
Run these commands:
zerotier-cli set <networkId> allowDefault=1 zerotier-cli set <networkId> allowGlobal=1 zerotier-cli set <networkId> allowManaged=1
NOTICE: these commands need to be executed on every client and jump host if using "connect and use" VPN mode.
The same as Part 1.
The same as Part 1.
Most OS can have only one effective default route. However, we can do this:
route add 0.0.0.0 mask 128.0.0.0 ZT_IPv4 route add 128.0.0.0 mask 128.0.0.0 ZT_IPv4 route add ::/1 ZT_IPv4 route add 8000::/1 ZT_IPv6
And this is how Zerotier does the Full Tunnel. The reason behind it is very simple and leaves it as a quiz for the reader.
You've reached the end of this page. And you may Go to index or visit my friends.
About me and contacts
Except where otherwise noted, this site is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License