OIDC groups implementation
- Add Groups field to User struct with JSON storage - Include GetGroups() and SetGroups() helper methods - Extract groups from OIDC claims in FromClaim() - Add database migration 202509161200 for groups column - Update config-example.yaml with groups scope - Add comprehensive documentation and testing
This commit is contained in:
parent
30d12dafed
commit
5abc3c87b2
29 changed files with 5088 additions and 3 deletions
217
docker-dev/NETWORK-ARCHITECTURE.md
Normal file
217
docker-dev/NETWORK-ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
# Network Architecture Documentation
|
||||
|
||||
This document provides a detailed explanation of the networking setup in the Headscale Docker development environment.
|
||||
|
||||
## Overview
|
||||
|
||||
The setup uses **two distinct networking layers** that work together to provide a complete Tailscale network simulation:
|
||||
|
||||
1. **Docker Bridge Network** - Infrastructure layer for container communication
|
||||
2. **Tailscale Overlay Network** - Encrypted VPN layer for secure data transmission
|
||||
|
||||
## Layer 1: Docker Bridge Network
|
||||
|
||||
### Network Configuration
|
||||
- **Subnet**: `10.99.0.0/24`
|
||||
- **Gateway**: `10.99.0.1`
|
||||
- **Network Name**: `headscale-dev_headscale-net`
|
||||
|
||||
### Container IP Assignments
|
||||
| Container | IP Address | Role |
|
||||
|-----------|------------|------|
|
||||
| headscale-server | `10.99.0.10` | Control plane server |
|
||||
| tailscale-client1 | `10.99.0.21` | Tailscale node 1 |
|
||||
| tailscale-client2 | `10.99.0.22` | Tailscale node 2 |
|
||||
| test-webserver | `10.99.0.30` | HTTP test server |
|
||||
|
||||
### Port Mappings
|
||||
|
||||
#### Headscale Server
|
||||
| Host Port | Container Port | Service |
|
||||
|-----------|----------------|---------|
|
||||
| 8180 | 8080 | HTTP API |
|
||||
| 9090 | 9090 | Metrics |
|
||||
| 50443 | 50443 | gRPC |
|
||||
|
||||
**Note**: Port 8180 is used on the host instead of 8080 to avoid conflicts with other services.
|
||||
|
||||
#### Other Services
|
||||
| Container | Exposed Ports | Purpose |
|
||||
|-----------|---------------|---------|
|
||||
| test-webserver | 80 (internal only) | HTTP test content |
|
||||
| tailscale-client1 | None exposed | VPN endpoint |
|
||||
| tailscale-client2 | None exposed | VPN endpoint |
|
||||
|
||||
## Layer 2: Tailscale Overlay Network
|
||||
|
||||
### Network Configuration
|
||||
- **IPv4 Subnet**: `100.64.0.0/10` (Tailscale CGNAT range)
|
||||
- **IPv6 Subnet**: `fd7a:115c:a1e0::/48` (Tailscale IPv6 range)
|
||||
- **Allocation Strategy**: Sequential
|
||||
|
||||
### Tailscale IP Assignments
|
||||
| Node | IPv4 Address | IPv6 Address | Hostname |
|
||||
|------|-------------|--------------|----------|
|
||||
| client1 | `100.64.0.1` | `fd7a:115c:a1e0::1` | client1 |
|
||||
| client2 | `100.64.0.2` | `fd7a:115c:a1e0::2` | client2 |
|
||||
|
||||
## Network Communication Flow
|
||||
|
||||
### 1. Control Plane Communication
|
||||
|
||||
```
|
||||
Tailscale Client → Docker Network → Headscale Server
|
||||
│ │ │
|
||||
100.64.0.1 10.99.0.21 10.99.0.10
|
||||
│ │ │
|
||||
└─────── HTTP/GRPC over ──────────┘
|
||||
headscale:8080
|
||||
```
|
||||
|
||||
- Clients connect to Headscale using Docker's internal DNS (`headscale:8080`)
|
||||
- Authentication happens via pre-auth keys
|
||||
- Headscale assigns Tailscale IP addresses from the `100.64.0.0/10` range
|
||||
- Policy enforcement and network map distribution
|
||||
|
||||
### 2. Data Plane Communication
|
||||
|
||||
```
|
||||
Client1 ←→ Encrypted Tailscale Tunnel ←→ Client2
|
||||
│ │
|
||||
100.64.0.1 100.64.0.2
|
||||
│ │
|
||||
10.99.0.21 ←── Docker Bridge Network ──→ 10.99.0.22
|
||||
```
|
||||
|
||||
When `client1` pings `client2`:
|
||||
1. **Application layer**: Uses Tailscale IP `100.64.0.2`
|
||||
2. **Encryption layer**: Tailscale encrypts the packet using WireGuard
|
||||
3. **Transport layer**: Encrypted packet travels via Docker network `10.99.0.22:port`
|
||||
4. **Decryption layer**: `client2` decrypts and processes the packet
|
||||
|
||||
**Key insight**: The ping result shows:
|
||||
```
|
||||
pong from client2 (100.64.0.2) via 10.99.0.22:49212 in 0s
|
||||
```
|
||||
This demonstrates how Tailscale IPs are used at the application level while Docker IPs handle the actual transport.
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### 1. Noise Protocol (Tailscale v2)
|
||||
- **Purpose**: Encrypts control plane communication between clients and Headscale
|
||||
- **Key Storage**: `/var/lib/headscale/noise_private.key`
|
||||
- **Protocol**: Noise_IK_25519_ChaChaPoly_BLAKE2s
|
||||
|
||||
### 2. WireGuard Encryption
|
||||
- **Purpose**: Encrypts data plane communication between Tailscale nodes
|
||||
- **Key Exchange**: Managed by Headscale control plane
|
||||
- **Cipher**: ChaCha20Poly1305
|
||||
|
||||
### 3. Access Control Lists (ACL)
|
||||
```json
|
||||
{
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["testuser@headscale"],
|
||||
"dst": ["testuser@headscale:*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- Controls which nodes can communicate with each other
|
||||
- Applied at the Tailscale overlay network level
|
||||
- Independent of Docker network security
|
||||
|
||||
## DNS Resolution
|
||||
|
||||
### Docker Internal DNS
|
||||
- `headscale` → `10.99.0.10` (Control plane access)
|
||||
- `client1` → `10.99.0.21` (Container hostname)
|
||||
- `client2` → `10.99.0.22` (Container hostname)
|
||||
- `webserver` → `10.99.0.30` (Test web server)
|
||||
|
||||
### Tailscale MagicDNS
|
||||
- `client1` → `100.64.0.1` (Tailscale hostname)
|
||||
- `client2` → `100.64.0.2` (Tailscale hostname)
|
||||
- Domain: `headscale.local` (configured in Headscale)
|
||||
|
||||
## Network Isolation and Security
|
||||
|
||||
### Container Isolation
|
||||
- Each container has its own network namespace
|
||||
- Containers can only communicate via the Docker bridge network
|
||||
- No direct host network access (except through port mappings)
|
||||
|
||||
### Tailscale Overlay Isolation
|
||||
- Encrypted tunnels between authorized nodes only
|
||||
- ACL policies enforce access control
|
||||
- Zero-trust architecture: containers on same Docker network still use encrypted communication
|
||||
|
||||
### Firewall Considerations
|
||||
- Docker bridge network: Internal communication only
|
||||
- Host ports: Only Headscale API (8180) exposed to host
|
||||
- Tailscale network: Controlled by ACL policies
|
||||
|
||||
## Debugging Network Issues
|
||||
|
||||
### Check Docker Network
|
||||
```bash
|
||||
# View network configuration
|
||||
docker network inspect headscale-dev_headscale-net
|
||||
|
||||
# Test Docker-level connectivity
|
||||
docker exec tailscale-client1 ping headscale
|
||||
docker exec tailscale-client1 ping 10.99.0.22
|
||||
```
|
||||
|
||||
### Check Tailscale Network
|
||||
```bash
|
||||
# View Tailscale status
|
||||
docker exec tailscale-client1 tailscale status
|
||||
|
||||
# Test Tailscale connectivity
|
||||
docker exec tailscale-client1 tailscale ping client2
|
||||
docker exec tailscale-client1 ping 100.64.0.2
|
||||
```
|
||||
|
||||
### Verify Control Plane
|
||||
```bash
|
||||
# Test Headscale API
|
||||
curl http://localhost:8180/health
|
||||
|
||||
# View registered nodes
|
||||
docker exec headscale-server headscale nodes list
|
||||
```
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### Latency
|
||||
- **Docker bridge**: Sub-millisecond latency (same host)
|
||||
- **Tailscale overlay**: Minimal additional latency due to encryption
|
||||
- **Control plane**: Periodic updates, not in data path
|
||||
|
||||
### Throughput
|
||||
- **Limited by**: Docker bridge network bandwidth and CPU encryption
|
||||
- **Typical**: Near-native performance for local container communication
|
||||
- **Encryption overhead**: Minimal with modern ChaCha20 implementation
|
||||
|
||||
### Scalability
|
||||
- **Current setup**: 2 clients, easily expandable
|
||||
- **Docker limitations**: Network MTU, container limits
|
||||
- **Headscale limitations**: Database backend (SQLite vs PostgreSQL)
|
||||
|
||||
## Real-World Mapping
|
||||
|
||||
This setup simulates real Tailscale deployments:
|
||||
|
||||
| Docker Environment | Real World |
|
||||
|--------------------|------------|
|
||||
| Docker bridge network | Internet infrastructure |
|
||||
| Container IP addresses | Public/private IP addresses |
|
||||
| Headscale control server | Tailscale SaaS control plane |
|
||||
| ACL policies | Corporate network policies |
|
||||
| Pre-auth keys | Device enrollment tokens |
|
||||
| Encrypted tunnels | WireGuard VPN connections |
|
||||
|
||||
The key difference is that in production, nodes are typically on different networks (home, office, cloud) rather than the same Docker host, but the Tailscale protocol behavior is identical.
|
||||
Loading…
Add table
Add a link
Reference in a new issue