





















In the ever-changing landscape of system administration, network configurations often need to grow and evolve to meet new challenges and requirements. This post details my journey from a simple VPS setup to a complex, multi-node network using FreeBSD, jails, VPNs, and advanced routing techniques. Along the way, I'll explore the reasons behind each change and delve into why certain solutions, while functional, may not always be ideal in the long run.
My story begins with a single VPS (let's call it VPSSmall) hosted on Hetzner, running FreeBSD. This initial configuration was straightforward and served its purpose well for a time:
bridge0) with IP 192.168.123.1This setup allowed for easy management of multiple services within isolated jails, all sharing the same network namespace.
As is often the case in system administration, my needs grew over time. The number of jails increased, and their resource requirements expanded. To address this, I added a second VPS (VPSBig) hosted on a Proxmox server. This VPS isn't directly exposed, and relies on NAT to connect to the outside world. This introduced a new challenge: how to maintain flexibility in moving jails between VPSs without changing their network configurations?
To solve this, I implemented the following setup:
bridge0 on VPSBig (without an IP)This configuration allowed for seamless movement of jails between nodes by simply transferring the ZFS dataset. The jails could retain their IP addresses regardless of which physical VPS they were running on.
While this setup was functional, it had some drawbacks that I'll discuss in the next section.
The bridged setup using ZeroTier, while effective, wasn't without its issues. Here's why I found bridging, in this case, wasn't an ideal long-term solution:
Performance Overhead: Bridging all traffic between VPSs can introduce additional latency and processing overhead, especially when dealing with high-volume traffic.
Scalability Concerns: As the number of VPSs and jails grows, managing a large bridged network becomes increasingly complex. Each new node added to the network increases the potential for broadcast storms and can lead to unnecessary traffic across the entire network.
Security Implications: In a bridged network, all nodes essentially exist on the same network segment. This can potentially allow for lateral movement between jails or VPSs if not carefully managed, increasing the attack surface.
Dependency on ZeroTier: While ZeroTier is a powerful tool, relying on a third-party service for critical infrastructure introduces an external point of failure and potential security considerations.
Limited Control: Bridging provides less granular control over traffic flow compared to routing. This can make it harder to implement complex network policies or optimize traffic paths.
Broadcast Domain Size: Large bridged networks can result in expansive broadcast domains, which can lead to increased network congestion and reduced overall performance.
These limitations prompted me to seek a more robust, scalable, and controllable solution, leading to the next evolution of my network setup.
To address the limitations of the bridged setup, I implemented a new configuration involving Wireguard and VXLAN:
This setup, described in detail here, offered several advantages:
While this setup was a significant improvement, it still relied on bridging via VXLAN, which didn't fully address all the scalability and control issues. This realization led to the final evolution of my network.
The last step in my network's evolution was to move from a bridged to a routed setup. This change offered even more flexibility and scalability. The new configuration:
This routed setup provides several key benefits:
To ensure jails on VPSBig use the Wireguard tunnel for outgoing traffic while VPSBig itself uses its default gateway, I leveraged FreeBSD's FIB feature. This allows for separate routing tables, providing even more flexibility in managing network traffic.
Edit /etc/sysctl.conf to enable multiple FIBs:
net.fibs=2
This allows me to use two separate routing tables.
[Interface]
PrivateKey = *VPSBigPrivateKey*
Address = 10.77.0.2/32,oneOfMyIpv6/128
Table = off
PostUp = route -q -n add -inet 0.0.0.0/0 -interface wg0 -fib 1
PostUp = route -q -n add -inet6 ::/1 -interface wg0 -fib 1
PostUp = route -q -n add -inet6 8000::/1 -interface wg0 -fib 1
[Peer]
PublicKey = *VPSSmallPublicKey*
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = *endpointip:port*
PresharedKey = *presharedkey*
PersistentKeepalive = 30
Let's break down this configuration:
Table = off: This disables Wireguard's automatic routing table management. We're doing this because we want to manually configure the routing.
The PostUp commands are crucial for our manual routing setup:
route -q -n add -inet 0.0.0.0/0 -interface wg0 -fib 1: This adds a default route for IPv4 traffic through the Wireguard interface (wg0) in the alternate routing table (FIB 1).The next two commands do the same for IPv6 traffic, covering the entire IPv6 address space (::/1 and 8000::/1 together cover all IPv6 addresses).
AllowedIPs = 0.0.0.0/0,::0/0: This tells Wireguard to route all traffic through this peer. However, because we've set Table = off, Wireguard won't actually create these routes - we're doing it manually with our PostUp commands.
PersistentKeepalive = 30: This sends a keepalive packet every 30 seconds, which is necessary because VPSBig is behind NAT and needs to keep the NAT session alive.
[Interface]
PrivateKey = *VPSSmallPrivateKey*
ListenPort = *port*
Address = 10.77.0.1/24,oneOfMyIpv6/128
[Peer]
PublicKey = *VPSSmallPublicKey*
PresharedKey = *presharedkey*
AllowedIPs = 10.77.0.2/32, 192.168.123.0/24, *theRemote/72ipv6class*/72
In this configuration:
Address = 10.77.0.1/24,oneOfMyIpv6/128: This sets up the Wireguard interface with an IPv4 and IPv6 address.
AllowedIPs = 10.77.0.2/32, 192.168.123.0/24, *theRemote/72ipv6class*/72: This tells Wireguard to route traffic for VPSBig's Wireguard IP (10.77.0.2), VPSBig's local subnet (192.168.123.0/24), and VPSBig's IPv6 subnet through this peer.
The use of FIB (Forwarding Information Base) 1 in the VPSBig configuration is key to our setup. By adding routes to FIB 1, we're creating a separate routing table that can be used by our jails. This allows us to:
We achieve this by configuring the jails to use FIB 1:
exec.prestart += "ifconfig epairXa fib 1";
exec.prestart += "ifconfig epairXb mtu 1380";
This ensures that each jail uses the alternate routing table (FIB 1) instead of the default routing table, effectively sending all its traffic through the Wireguard tunnel.
If the WireGuard MTU is 1420, setting the jail's MTU to 1380 should be safe enough.
To complete the setup, we need to configure NAT on VPSSmall to allow the jails on VPSBig to access the internet:
nat on vtnet0 from 192.168.123.0/24 to ! <private> -> vtnet0:0
This NAT rule translates the source IP of packets coming from VPSBig's subnet (192.168.123.0/24) to VPSSmall's public IP when they're destined for non-private IP addresses.
My journey from a simple single-VPS setup to this complex, multi-node network illustrates the power and flexibility of FreeBSD. By transitioning from a bridged to a routed setup, I've created a solution that offers improved scalability, security, and control.
Key takeaways from this evolution include:
Whether you're managing a small personal server or a large-scale infrastructure, the techniques described here can help you build a robust and adaptable network. Remember, network design is an iterative process. Don't be afraid to evolve your setup as your needs change.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。