From 6ea1a37bef6e0fb6990ea7fd19815442c18676ae Mon Sep 17 00:00:00 2001 From: goeranh Date: Fri, 13 Mar 2026 17:32:05 +0100 Subject: [PATCH] add v6proxy docs --- README.md | 11 +- hosts/v6proxy/README.md | 344 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 hosts/v6proxy/README.md diff --git a/README.md b/README.md index 617b622..7f601fe 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Declarative infrastructure management for StuRa HTW Dresden using NixOS and a fl This infrastructure uses a flake-based approach with automatic host discovery: - **Centralized reverse proxy**: HAProxy at 141.56.51.1 routes all traffic via SNI inspection and HTTP host headers +- **IPv6 gateway**: Hetzner VPS at 2a01:4f8:1c19:96f8::1 forwards IPv6 traffic to the IPv4 proxy - **Automatic host discovery**: Each subdirectory in `hosts/` becomes a NixOS configuration via `builtins.readDir` - **Global configuration**: Settings in `default.nix` are automatically applied to all hosts - **ACME certificates**: All services use Let's Encrypt certificates managed locally on each host @@ -31,6 +32,11 @@ stura-infra/ │ │ ├── hardware-configuration.nix │ │ ├── hetzner-disk.nix │ │ └── README.md +│ ├── v6proxy/ # IPv6 gateway (Hetzner VPS) +│ │ ├── default.nix +│ │ ├── hardware-configuration.nix +│ │ ├── hetzner-disk.nix +│ │ └── README.md │ ├── git/ # Forgejo git server │ │ └── default.nix │ ├── wiki/ # MediaWiki instance @@ -47,6 +53,7 @@ stura-infra/ | Host | IP | Type | Services | Documentation | |------|-----|------|----------|---------------| | proxy | 141.56.51.1 | VM | HAProxy, SSH Jump | [hosts/proxy/README.md](hosts/proxy/README.md) | +| v6proxy | 178.104.18.93 (IPv4)
2a01:4f8:1c19:96f8::1 (IPv6) | Hetzner VPS | HAProxy (IPv6 Gateway) | [hosts/v6proxy/README.md](hosts/v6proxy/README.md) | | git | 141.56.51.7 | LXC | Forgejo, Nginx | [hosts/git/README.md](hosts/git/README.md) | | wiki | 141.56.51.13 | LXC | MediaWiki, MariaDB, Apache | [hosts/wiki/README.md](hosts/wiki/README.md) | | redmine | 141.56.51.15 | LXC | Redmine, Nginx | [hosts/redmine/README.md](hosts/redmine/README.md) | @@ -193,9 +200,9 @@ The following DNS records must be configured for the current infrastructure: |------|------|-----|---------| | *.htw.stura-dresden.de | CNAME | proxy.htw.stura-dresden.de | Reverse proxy | | proxy.htw.stura-dresden.de | A | 141.56.51.1 | Proxy IPv4 | -| proxy.htw.stura-dresden.de | AAAA | 2a01:4f8:1c19:96f8::1 | Proxy IPv6 | +| proxy.htw.stura-dresden.de | AAAA | 2a01:4f8:1c19:96f8::1 | IPv6 Gateway (v6proxy) | -**Note**: All public services point to the proxy IP (141.56.51.1). The proxy handles SNI-based routing to backend hosts. Backend IPs are internal and not exposed in DNS. +**Note**: All public services point to the proxy IPs. The IPv4 proxy (141.56.51.1) handles SNI-based routing to backend hosts. The IPv6 gateway (v6proxy at 2a01:4f8:1c19:96f8::1) forwards all IPv6 traffic to the IPv4 proxy. Backend IPs are internal and not exposed in DNS. Additional services managed by the proxy (not in this repository): - stura.htw-dresden.de → Plone diff --git a/hosts/v6proxy/README.md b/hosts/v6proxy/README.md new file mode 100644 index 0000000..eedb6c4 --- /dev/null +++ b/hosts/v6proxy/README.md @@ -0,0 +1,344 @@ +# v6proxy Host - IPv6 Gateway + +IPv6 gateway proxy hosted on Hetzner VPS, forwarding all IPv6 traffic to the main IPv4 proxy. + +## Overview + +- **Hostname**: v6proxy +- **IPv4 Address**: 178.104.18.93/32 +- **IPv6 Address**: 2a01:4f8:1c19:96f8::1/64 +- **Type**: Hetzner VPS (Full VM) +- **Services**: HAProxy (IPv6 to IPv4 forwarding) +- **Role**: IPv6 gateway for StuRa HTW Dresden infrastructure + +## Architecture + +The v6proxy serves as an IPv6 gateway because the main infrastructure at 141.56.51.0/24 is IPv4-only: + +- All IPv6 DNS records (AAAA) point to this host (2a01:4f8:1c19:96f8::1) +- HAProxy forwards all IPv6 HTTP/HTTPS traffic to the main proxy at 141.56.51.1 +- The main proxy then handles routing to backend services +- Simple pass-through configuration - no SNI inspection or routing logic + +## Why This Host Exists + +The HTW Dresden network (141.56.51.0/24) does not have native IPv6 connectivity. This Hetzner VPS provides: + +1. **IPv6 connectivity**: Public IPv6 address for all services +2. **Transparent forwarding**: All traffic is forwarded to the IPv4 proxy +3. **No maintenance overhead**: Simple configuration, no routing logic + +This allows all StuRa services to be accessible via IPv6 without requiring IPv6 support in the HTW network. + +## Services + +### HAProxy + +HAProxy runs in simple TCP forwarding mode: + +**HTTP (Port 80)** +- Binds to IPv6 `:::80` +- Forwards all traffic to `141.56.51.1:80` +- No HTTP inspection or routing + +**HTTPS (Port 443)** +- Binds to IPv6 `:::443` +- Forwards all traffic to `141.56.51.1:443` +- No SNI inspection or TLS termination + +**Key features:** +- Logging: All connections logged to systemd journal +- Stats page: Available at http://127.0.0.1:8404/stats (localhost only) +- Max connections: 50,000 +- Buffer size: 32,762 bytes +- Timeouts: 5s connect, 30s client/server + +### Configuration Philosophy + +Unlike the main proxy at 141.56.51.1, this proxy is **intentionally simple**: +- No SNI inspection +- No HTTP host header routing +- No ACME challenge handling +- Just pure TCP forwarding + +All routing logic happens at the main IPv4 proxy. This keeps the v6proxy configuration minimal and reduces maintenance burden. + +## Deployment Type + +The v6proxy is a **Hetzner VPS** (full VM): +- Hosted outside HTW network +- Uses Hetzner-specific disk layout (hetzner-disk.nix) +- Network interface: `eth0` +- Both IPv4 and IPv6 connectivity + +## Network Configuration + +### IPv4 +- **Address**: 178.104.18.93/32 +- **Gateway**: 172.31.1.1 +- **Interface**: eth0 + +### IPv6 +- **Address**: 2a01:4f8:1c19:96f8::1/64 +- **Gateway**: fe80::1 (link-local) +- **Route**: Default route via fe80::1 +- **Interface**: eth0 + +### DNS +- **Nameservers**: 9.9.9.9, 1.1.1.1 (Quad9 and Cloudflare) +- Uses public DNS servers (not HTW internal DNS) + +### Firewall +- **Firewall**: nftables enabled +- **Open ports**: 22, 80, 443 + +## DNS Configuration + +For IPv6 support, configure AAAA records pointing to this host: + +``` +proxy.htw.stura-dresden.de AAAA 2a01:4f8:1c19:96f8::1 +*.htw.stura-dresden.de CNAME proxy.htw.stura-dresden.de +``` + +This provides IPv6 access to all services while IPv4 traffic continues to use the main proxy (141.56.51.1). + +## Deployment + +See the [main README](../../README.md) for deployment methods. + +### Initial Installation + +**Using nixos-anywhere (recommended):** +```bash +nix run github:nix-community/nixos-anywhere -- --flake .#v6proxy --target-host root@178.104.18.93 +``` + +This handles disk partitioning via disko automatically. + +### Updates + +```bash +# From local machine +nixos-rebuild switch --flake .#v6proxy --target-host root@178.104.18.93 + +# Or use auto-generated script +nix run .#v6proxy-update +``` + +## Disko Configuration + +The v6proxy uses the Hetzner-specific disk layout (hetzner-disk.nix): +- **Filesystem**: Btrfs or Ext4 (Hetzner default) +- Declarative disk management via disko +- Automatic partitioning on installation + +## Traffic Flow + +IPv6 request flow: + +1. Client connects to `2a01:4f8:1c19:96f8::1` (v6proxy) +2. v6proxy forwards to `141.56.51.1:443` (main IPv4 proxy) +3. Main proxy performs SNI inspection and routes to backend +4. Backend responds through the chain + +For the client, the IPv6 connectivity is transparent - they don't know the backend infrastructure is IPv4-only. + +## HAProxy Configuration + +The HAProxy configuration is minimal: + +```haproxy +frontend http-in + bind :::80 + use_backend http_80 + +frontend sni_router + bind :::443 + mode tcp + use_backend http_443 + +backend http_80 + mode http + server proxy 141.56.51.1:80 + +backend http_443 + mode tcp + server proxy 141.56.51.1:443 +``` + +This is intentionally simple - all routing intelligence is at 141.56.51.1. + +## HAProxy Stats + +Access HAProxy statistics page (localhost only): + +```bash +# SSH into v6proxy +ssh root@178.104.18.93 + +# Access stats via curl +curl http://127.0.0.1:8404/stats + +# Or forward port to your local machine +ssh -L 8404:127.0.0.1:8404 root@178.104.18.93 +# Then browse to http://localhost:8404/stats +``` + +The stats page shows: +- Current connections to main proxy backend +- Traffic statistics +- Connection status + +## Monitoring + +### Check HAProxy Status + +```bash +# HAProxy service status +systemctl status haproxy + +# View HAProxy logs +journalctl -u haproxy -f + +# Check configuration +haproxy -c -f /etc/haproxy/haproxy.cfg +``` + +### Test Connectivity + +```bash +# Test IPv6 HTTP forwarding +curl -6 -v http://[2a01:4f8:1c19:96f8::1]/ + +# Test IPv6 HTTPS forwarding +curl -6 -vk https://[2a01:4f8:1c19:96f8::1]/ + +# Test backend connectivity (IPv4 to main proxy) +curl -v http://141.56.51.1/ +curl -vk https://141.56.51.1/ + +# Check IPv6 routing +ip -6 route show +ping6 2a01:4f8:1c19:96f8::1 +``` + +## Troubleshooting + +### HAProxy not starting + +```bash +# Check HAProxy status +systemctl status haproxy + +# Check configuration syntax +haproxy -c -f /etc/haproxy/haproxy.cfg + +# View HAProxy logs +journalctl -u haproxy -f +``` + +### IPv6 connectivity issues + +```bash +# Verify IPv6 address is configured +ip -6 addr show eth0 + +# Check IPv6 routing +ip -6 route show + +# Test IPv6 connectivity +ping6 2606:4700:4700::1111 # Cloudflare DNS + +# Check IPv6 firewall rules +nft list ruleset | grep ip6 +``` + +### Backend (main proxy) unreachable + +```bash +# Test IPv4 connectivity to main proxy +ping 141.56.51.1 +curl -v http://141.56.51.1/ +curl -vk https://141.56.51.1/ + +# Check HAProxy backend status +curl http://127.0.0.1:8404/stats | grep proxy + +# View connection errors +journalctl -u haproxy | grep -i error +``` + +### DNS not resolving + +```bash +# Check nameserver configuration +cat /etc/resolv.conf + +# Test DNS resolution +dig git.adm.htw.stura-dresden.de A +dig git.adm.htw.stura-dresden.de AAAA + +# Test with specific nameserver +dig @9.9.9.9 git.adm.htw.stura-dresden.de +``` + +## Security Considerations + +- **No TLS termination**: Traffic is passed through encrypted to main proxy +- **No deep packet inspection**: Simple TCP forwarding only +- **Minimal attack surface**: No routing logic or service-specific configuration +- **Public IPv6 address**: Exposed to the internet, firewall must be properly configured + +## Performance Considerations + +- **Additional hop**: IPv6 traffic goes through an extra proxy hop +- **Latency**: Hetzner → HTW network adds some latency +- **Bandwidth**: Hetzner provides high bandwidth, unlikely to be a bottleneck +- **Connection limits**: HAProxy configured for 50,000 concurrent connections + +For most use cases, the additional latency is negligible (typically <10ms within Germany). + +## Cost and Hosting + +- **Provider**: Hetzner Cloud +- **Type**: VPS (Virtual Private Server) +- **Location**: Germany (likely Falkenstein or Helsinki datacenter) +- **Cost**: Minimal - basic VPS tier sufficient for forwarding traffic + +## Future Improvements + +Possible improvements (not currently needed): + +1. **Native IPv6 at HTW**: If HTW network gains IPv6, this proxy can be decommissioned +2. **GeoDNS**: Use GeoDNS to route IPv4 and IPv6 separately +3. **Monitoring**: Add automated monitoring and alerting +4. **Failover**: Add a second IPv6 proxy for redundancy + +## Files and Directories + +- **HAProxy config**: `/etc/haproxy/haproxy.cfg` (generated by Nix) +- **Disk config**: `./hetzner-disk.nix` (disko configuration) +- **Hardware config**: `./hardware-configuration.nix` (Hetzner VPS hardware) +- **NixOS config**: `./default.nix` (v6proxy configuration) + +## Relationship to Main Proxy + +| Feature | v6proxy (IPv6 Gateway) | proxy (Main Proxy) | +|---------|------------------------|-------------------| +| IP Version | IPv4 + IPv6 | IPv4 only | +| Location | Hetzner Cloud | HTW network (141.56.51.0/24) | +| Function | Simple forwarding | SNI routing, service routing | +| Complexity | Minimal | Complex routing logic | +| HAProxy Mode | TCP forwarding | TCP + HTTP with SNI inspection | +| TLS Handling | Pass-through | Pass-through (SNI inspection) | +| ACME Handling | None | Forwards challenges to backends | + +The v6proxy is intentionally minimal - all intelligence lives at the main proxy. + +## See Also + +- [Main README](../../README.md) - Deployment methods and architecture +- [Proxy README](../proxy/README.md) - Main IPv4 proxy configuration +- [HAProxy Documentation](http://www.haproxy.org/#docs) +- [Hetzner Cloud Docs](https://docs.hetzner.com/cloud/)