|
| 1 | +# 🌐 Networking |
| 2 | + |
| 3 | +DAppNode's networking system provides seamless connectivity between containers, external services, and end users through a sophisticated Docker networking architecture combined with DNS resolution, port forwarding, and accessibility features. |
| 4 | + |
| 5 | +## 🏗️ Network Architecture |
| 6 | + |
| 7 | +``` |
| 8 | +┌─────────────────────────────────────────────────────────────┐ |
| 9 | +│ DAppNode Network Stack │ |
| 10 | +├─────────────────────────────────────────────────────────────┤ |
| 11 | +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ |
| 12 | +│ │ Admin UI │ │ Bind │ │ Package Services │ │ |
| 13 | +│ │ my.dappnode │ │ DNS Server │ │ (Various IPs) │ │ |
| 14 | +│ │172.33.1.7 │ │172.33.1.2 │ │ │ │ |
| 15 | +│ └─────────────┘ └─────────────┘ └─────────────────────┘ │ |
| 16 | +├─────────────────────────────────────────────────────────────┤ |
| 17 | +│ dncore_network │ |
| 18 | +│ 172.33.0.0/16 │ |
| 19 | +├─────────────────────────────────────────────────────────────┤ |
| 20 | +│ Docker Bridge Network │ |
| 21 | +├─────────────────────────────────────────────────────────────┤ |
| 22 | +│ Host Network Stack │ |
| 23 | +│ (Ubuntu/Debian) │ |
| 24 | +└─────────────────────────────────────────────────────────────┘ |
| 25 | +``` |
| 26 | + |
| 27 | +## 🐳 Docker Networks and Aliases |
| 28 | + |
| 29 | +### Core Network Configuration |
| 30 | +DAppNode creates and manages a dedicated Docker network for all packages: |
| 31 | + |
| 32 | +```typescript |
| 33 | +// From packages/daemons/src/dockerNetworkConfigs/index.ts |
| 34 | +async function ensureDockerNetworkConfig({ |
| 35 | + networkName, // "dncore_network" |
| 36 | + subnet, // "172.33.0.0/16" |
| 37 | + dappmanagerIp, // "172.33.1.7" |
| 38 | + bindIp // "172.33.1.2" |
| 39 | +}: NetworkConfig): Promise<void> { |
| 40 | + // 1. Create the new docker network |
| 41 | + await createDockerNetwork({ networkName, subnet }); |
| 42 | + |
| 43 | + // 2. Connect all DAppNode packages to the network |
| 44 | + const packages = await packagesGet(); |
| 45 | + for (const pkg of packages) { |
| 46 | + writeDockerNetworkConfig({ pkg, networkName }); |
| 47 | + await dockerComposeUpPackage({ |
| 48 | + dnpName: pkg.dnpName, |
| 49 | + upAll: false, |
| 50 | + dockerComposeUpOptions: { noRecreate: true } |
| 51 | + }); |
| 52 | + } |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +### Network Segmentation |
| 57 | +DAppNode uses multiple network segments for different purposes: |
| 58 | + |
| 59 | +#### Core Network (`dncore_network`) |
| 60 | +- **Purpose**: System-critical services and user packages |
| 61 | +- **Subnet**: `172.33.0.0/16` (65,536 IP addresses) |
| 62 | +- **Reserved IPs**: |
| 63 | + - `172.33.1.2`: Bind DNS server |
| 64 | + - `172.33.1.7`: DAppManager and Admin UI |
| 65 | + - `172.33.1.x`: Core services |
| 66 | + - `172.33.x.x`: User packages (auto-assigned) |
| 67 | + |
| 68 | +#### Staker Network (`staker_network`) |
| 69 | +- **Purpose**: Ethereum staking infrastructure |
| 70 | +- **Isolation**: Separated from general packages for security |
| 71 | +- **Components**: Execution clients, consensus clients, validators |
| 72 | + |
| 73 | +```typescript |
| 74 | +// From packages/daemons/src/dockerNetworkConfigs/createStakerNetworkAndConnectStakerPkgs.ts |
| 75 | +export async function createStakerNetworkAndConnectStakerPkgs( |
| 76 | + execution: Execution, |
| 77 | + consensus: Consensus, |
| 78 | + signer: Signer, |
| 79 | + mevBoost: MevBoost |
| 80 | +): Promise<void> { |
| 81 | + // Create isolated network for staking infrastructure |
| 82 | + await createDockerNetwork({ |
| 83 | + networkName: params.STAKER_NETWORK_NAME, |
| 84 | + subnet: params.STAKER_NETWORK_SUBNET |
| 85 | + }); |
| 86 | + |
| 87 | + // Connect staking packages to both networks |
| 88 | + const stakerPackages = [execution, consensus, signer, mevBoost]; |
| 89 | + for (const pkg of stakerPackages) { |
| 90 | + await connectPkgContainers(pkg, params.STAKER_NETWORK_NAME); |
| 91 | + } |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +### Container Aliases |
| 96 | +Each package gets predictable network aliases: |
| 97 | + |
| 98 | +```yaml |
| 99 | +# docker-compose.yml example |
| 100 | +services: |
| 101 | + geth: |
| 102 | + image: ethereum/client-go:latest |
| 103 | + networks: |
| 104 | + dncore_network: |
| 105 | + aliases: |
| 106 | + - geth.dappnode # Primary alias |
| 107 | + - geth # Short alias |
| 108 | + - execution.eth.dappnode # Functional alias |
| 109 | +``` |
| 110 | +
|
| 111 | +## 📍 DNS Resolution with Bind |
| 112 | +
|
| 113 | +### Bind DNS Server |
| 114 | +DAppNode runs its own DNS server (Bind9) to provide: |
| 115 | +- **Internal Service Discovery**: Packages find each other by name |
| 116 | +- **External DNS Resolution**: Standard internet DNS queries |
| 117 | +- **Custom Domain Routing**: `.dappnode` domain resolution |
| 118 | + |
| 119 | +```typescript |
| 120 | +// From packages/dappmanager/src/calls/bindDnpService.ts |
| 121 | +interface DnsRecord { |
| 122 | + name: string; // "geth.dappnode" |
| 123 | + type: "A" | "CNAME"; // Record type |
| 124 | + target: string; // IP address or hostname |
| 125 | + ttl?: number; // Time to live |
| 126 | +} |
| 127 | +
|
| 128 | +export async function updateDnsRecords(records: DnsRecord[]): Promise<void> { |
| 129 | + // Updates Bind configuration with new DNS records |
| 130 | + // Reloads DNS server to apply changes |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### DNS Query Flow |
| 135 | +``` |
| 136 | +User Request: http://geth.dappnode |
| 137 | + │ |
| 138 | + ▼ |
| 139 | +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ |
| 140 | +│ Browser │───►│ Bind Server │───►│ Package │ |
| 141 | +│ │ │ 172.33.1.2 │ │ Geth │ |
| 142 | +└─────────────┘ └─────────────┘ └─────────────┘ |
| 143 | +``` |
| 144 | +
|
| 145 | +### Dynamic DNS Updates |
| 146 | +As packages are installed/removed, DNS records are automatically updated: |
| 147 | +
|
| 148 | +```typescript |
| 149 | +// From packages/daemons/src/dockerNetworkConfigs/writeDockerNetworkConfig.ts |
| 150 | +export function writeDockerNetworkConfig({ |
| 151 | + pkg, |
| 152 | + networkName |
| 153 | +}: { |
| 154 | + pkg: InstalledPackageDataApiReturn; |
| 155 | + networkName: string; |
| 156 | +}): void { |
| 157 | + // 1. Read existing docker-compose.yml |
| 158 | + const compose = readComposeFile(pkg.composePath); |
| 159 | + |
| 160 | + // 2. Add network configuration to all services |
| 161 | + for (const serviceName in compose.services) { |
| 162 | + compose.services[serviceName].networks = { |
| 163 | + [networkName]: { |
| 164 | + aliases: [ |
| 165 | + `${serviceName}.${pkg.dnpName}`, |
| 166 | + `${serviceName}.dappnode`, |
| 167 | + serviceName |
| 168 | + ] |
| 169 | + } |
| 170 | + }; |
| 171 | + } |
| 172 | + |
| 173 | + // 3. Write updated compose file |
| 174 | + writeComposeFile(pkg.composePath, compose); |
| 175 | +} |
| 176 | +``` |
| 177 | + |
| 178 | +## 🔓 Package Accessibility |
| 179 | + |
| 180 | +### Access Control Mechanisms |
| 181 | +DAppNode provides multiple ways to control package access: |
| 182 | + |
| 183 | +#### Internal-Only Packages |
| 184 | +- **No external access**: Only accessible within DAppNode network |
| 185 | +- **Example**: Database services, internal APIs |
| 186 | +- **Security**: Protected from external threats |
| 187 | + |
| 188 | +#### Public Access (HTTP/HTTPS) |
| 189 | +- **Web interface exposure**: Accessible via browser |
| 190 | +- **Domain mapping**: Custom domains like `grafana.dappnode` |
| 191 | +- **HTTPS termination**: Automatic SSL certificates |
| 192 | + |
| 193 | +#### Custom Port Exposure |
| 194 | +```yaml |
| 195 | +# docker-compose.yml |
| 196 | +services: |
| 197 | + service: |
| 198 | + ports: |
| 199 | + - "8080:80" # Expose port 80 as 8080 on host |
| 200 | + - "443:443" # Direct HTTPS exposure |
| 201 | +``` |
| 202 | +
|
| 203 | +### HTTPS Portal Integration |
| 204 | +DAppNode includes an HTTPS portal for secure web access: |
| 205 | +
|
| 206 | +```typescript |
| 207 | +// From packages/httpsPortal/src/index.ts |
| 208 | +interface HttpsPortalConfig { |
| 209 | + domain: string; // "grafana.dappnode" |
| 210 | + targetUrl: string; // "http://grafana:3000" |
| 211 | + ssl: boolean; // Enable HTTPS |
| 212 | + forceSSL: boolean; // Redirect HTTP to HTTPS |
| 213 | + certificateSource: 'letsencrypt' | 'self-signed'; |
| 214 | +} |
| 215 | +``` |
| 216 | + |
| 217 | +### Access Patterns |
| 218 | +1. **Direct Access**: `http://packagename.dappnode:port` |
| 219 | +2. **Proxied Access**: `https://packagename.dappnode` (via HTTPS portal) |
| 220 | +3. **Admin UI Integration**: Embedded iframes or links |
| 221 | +4. **API Access**: RESTful APIs with authentication |
| 222 | + |
| 223 | +## 🌍 External Connectivity |
| 224 | + |
| 225 | +### Port Forwarding and UPnP |
| 226 | +DAppNode automatically configures router port forwarding: |
| 227 | + |
| 228 | +```typescript |
| 229 | +// From packages/upnpc/src/upnpc.ts |
| 230 | +interface PortMapping { |
| 231 | + internalPort: number; // Port inside DAppNode |
| 232 | + externalPort: number; // Port on router |
| 233 | + protocol: 'TCP' | 'UDP'; // Network protocol |
| 234 | + description: string; // Human-readable description |
| 235 | +} |
| 236 | + |
| 237 | +export async function addUPnPMapping(mapping: PortMapping): Promise<void> { |
| 238 | + // Uses UPnP protocol to configure router automatically |
| 239 | + // Creates NAT traversal rules for external access |
| 240 | +} |
| 241 | +``` |
| 242 | + |
| 243 | +### Common Port Mappings |
| 244 | +- **22/TCP**: SSH access (if enabled) |
| 245 | +- **80/TCP**: HTTP web interface |
| 246 | +- **443/TCP**: HTTPS web interface |
| 247 | +- **30303/TCP**: Ethereum P2P (Geth) |
| 248 | +- **9000/TCP**: Ethereum Beacon (Prysm) |
| 249 | +- **Custom**: Package-specific ports |
| 250 | + |
| 251 | +### UPnP Discovery Process |
| 252 | +``` |
| 253 | +1. DAppNode discovers router via UPnP |
| 254 | +2. Queries existing port mappings |
| 255 | +3. Creates necessary port forwards |
| 256 | +4. Monitors and refreshes mappings |
| 257 | +5. Removes mappings when packages are uninstalled |
| 258 | +``` |
| 259 | + |
| 260 | +## 🔧 Advanced Networking Features |
| 261 | + |
| 262 | +### Load Balancing |
| 263 | +For packages with multiple instances: |
| 264 | + |
| 265 | +```yaml |
| 266 | +# docker-compose.yml with load balancing |
| 267 | +services: |
| 268 | + app: |
| 269 | + image: myapp:latest |
| 270 | + deploy: |
| 271 | + replicas: 3 |
| 272 | + networks: |
| 273 | + - dncore_network |
| 274 | + |
| 275 | + nginx: |
| 276 | + image: nginx:alpine |
| 277 | + volumes: |
| 278 | + - ./nginx.conf:/etc/nginx/nginx.conf |
| 279 | + networks: |
| 280 | + - dncore_network |
| 281 | +``` |
| 282 | +
|
| 283 | +### Service Mesh Integration |
| 284 | +- **Inter-service Communication**: Secure communication between packages |
| 285 | +- **Traffic Management**: Advanced routing and load balancing |
| 286 | +- **Observability**: Network traffic monitoring and analysis |
| 287 | +
|
| 288 | +### VPN Integration |
| 289 | +DAppNode supports VPN connections for secure remote access: |
| 290 | +
|
| 291 | +```typescript |
| 292 | +// VPN configuration for remote access |
| 293 | +interface VpnConfig { |
| 294 | + protocol: 'OpenVPN' | 'WireGuard'; |
| 295 | + serverAddress: string; |
| 296 | + port: number; |
| 297 | + encryption: string; |
| 298 | + authentication: 'certificate' | 'psk'; |
| 299 | +} |
| 300 | +``` |
| 301 | + |
| 302 | +## 📊 Network Monitoring |
| 303 | + |
| 304 | +### Connection Health Monitoring |
| 305 | +```typescript |
| 306 | +// From packages/notifications/src/networkMonitoring.ts |
| 307 | +interface NetworkHealthCheck { |
| 308 | + target: string; // Target service |
| 309 | + type: 'http' | 'tcp' | 'udp' | 'icmp'; |
| 310 | + timeout: number; // Connection timeout |
| 311 | + interval: number; // Check interval |
| 312 | + expectedResponse?: string; // Expected response content |
| 313 | +} |
| 314 | + |
| 315 | +export async function checkNetworkHealth(checks: NetworkHealthCheck[]): Promise<HealthReport> { |
| 316 | + // Performs network connectivity checks |
| 317 | + // Reports on service availability and performance |
| 318 | +} |
| 319 | +``` |
| 320 | + |
| 321 | +### Traffic Analytics |
| 322 | +- **Bandwidth Usage**: Per-package network usage tracking |
| 323 | +- **Connection Patterns**: Inter-service communication analysis |
| 324 | +- **Performance Metrics**: Latency, throughput, error rates |
| 325 | + |
| 326 | +### Network Troubleshooting |
| 327 | +Built-in tools for network diagnosis: |
| 328 | + |
| 329 | +```typescript |
| 330 | +// Network diagnostic tools |
| 331 | +export async function runNetworkDiagnostics(): Promise<DiagnosticReport> { |
| 332 | + return { |
| 333 | + dnsResolution: await testDnsResolution(), |
| 334 | + containerConnectivity: await testContainerConnectivity(), |
| 335 | + externalConnectivity: await testExternalConnectivity(), |
| 336 | + portAccessibility: await testPortAccessibility(), |
| 337 | + upnpStatus: await checkUpnpStatus() |
| 338 | + }; |
| 339 | +} |
| 340 | +``` |
| 341 | + |
| 342 | +## 🛡️ Network Security |
| 343 | + |
| 344 | +### Firewall Configuration |
| 345 | +- **Default Deny**: Block all unnecessary traffic |
| 346 | +- **Whitelist Rules**: Allow only required connections |
| 347 | +- **Package Isolation**: Prevent unauthorized inter-package communication |
| 348 | + |
| 349 | +### SSL/TLS Termination |
| 350 | +```typescript |
| 351 | +// Automatic SSL certificate management |
| 352 | +interface CertificateConfig { |
| 353 | + domain: string; |
| 354 | + provider: 'letsencrypt' | 'self-signed'; |
| 355 | + autoRenewal: boolean; |
| 356 | + keySize: 2048 | 4096; |
| 357 | +} |
| 358 | +``` |
| 359 | + |
| 360 | +### Network Segmentation Security |
| 361 | +- **Core Services Protection**: Critical services on separate subnet |
| 362 | +- **User Package Isolation**: Prevent packages from accessing core services |
| 363 | +- **Staker Network Security**: Dedicated network for staking infrastructure |
| 364 | + |
| 365 | +## 🔗 Related Systems |
| 366 | + |
| 367 | +- **[Docker Integration](Docker-Integration.md)**: Container orchestration and networking |
| 368 | +- **[PoS in DAppNode](PoS-in-DAppNode.md)**: Staker network configuration |
| 369 | +- **[Admin UI](Admin-UI.md)**: Network management interface |
| 370 | +- **[Monitoring & Metrics](Monitoring-Metrics.md)**: Network performance monitoring |
| 371 | + |
| 372 | +--- |
| 373 | + |
| 374 | +> **Technical Implementation**: The networking system is implemented across multiple packages including `packages/daemons/src/dockerNetworkConfigs/`, `packages/httpsPortal/`, and `packages/upnpc/`. |
0 commit comments