feat: expose port 4017 in Dockerfile for relayserver

- Added EXPOSE directive to allow external access to the relayserver application on port 4017 - Ensures the container can receive incoming connections as expected by the application

lemon-mint committed Oct 29, 2025 at 15:38 UTC 65c306d6ec1d76ba38a8a8cd73129434da143b70
3 files changed +2 -484
DOCKER_BUILD_VERIFICATION.md deleted
-229
@@ -1,229 +0,0 @@
1 -# Docker Build Verification
2 -
3 -## Build Process Flow
4 -
5 -```
6 -┌─────────────────────────────────────────────────────────┐
7 -│ Stage 1: WASM Builder (rust:1-bullseye) │
8 -│ │
9 -│ 1. Install wasm-pack │
10 -│ 2. Run: make build-wasm │
11 -│ ├─ wasm-pack build --target web │
12 -│ ├─ cp pkg/* → cmd/relay-server/wasm/ │
13 -│ ├─ cp sw-proxy.js → cmd/relay-server/wasm/ │
14 -│ └─ cp sw.js → cmd/relay-server/wasm/ │
15 -│ │
16 -│ Output: cmd/relay-server/wasm/ │
17 -│ ├── relaydns_wasm.js │
18 -│ ├── relaydns_wasm_bg.wasm │
19 -│ ├── relaydns_wasm_sw.js │
20 -│ ├── sw-proxy.js ← E2EE Proxy │
21 -│ └── sw.js ← Caching │
22 -└─────────────────────────────────────────────────────────┘
23 - │ COPY --from=wasm-builder
24 - ▼
25 -┌─────────────────────────────────────────────────────────┐
26 -│ Stage 2: Go Builder (golang:1) │
27 -│ │
28 -│ 1. Copy go.mod, go.sum │
29 -│ 2. go mod download │
30 -│ 3. Copy source code │
31 -│ 4. COPY WASM files from Stage 1 │
32 -│ 5. Run: make build-server │
33 -│ └─ go build (embeds wasm/ via //go:embed) │
34 -│ │
35 -│ Output: bin/relayserver (18MB with embedded WASM) │
36 -└─────────────────────────────────────────────────────────┘
37 - │ COPY --from=builder
38 - ▼
39 -┌─────────────────────────────────────────────────────────┐
40 -│ Stage 3: Runtime (distroless/static-debian12) │
41 -│ │
42 -│ Final binary: /usr/bin/relayserver │
43 -│ ├─ Contains all WASM files │
44 -│ ├─ Contains service workers │
45 -│ └─ Ready to serve E2EE proxy │
46 -└─────────────────────────────────────────────────────────┘
47 -```
48 -
49 -## Files Embedded in Binary
50 -
51 -```go
52 -// view.go line 28-29
53 -//go:embed wasm
54 -var wasmFS embed.FS
55 -```
56 -
57 -**Embedded files:**
58 -- `/pkg/relaydns_wasm.js` (47KB)
59 -- `/pkg/relaydns_wasm_bg.wasm` (465KB)
60 -- `/pkg/relaydns_wasm_sw.js` (52KB)
61 -- `/sw-proxy.js` (5KB) ← **E2EE Proxy Service Worker**
62 -- `/sw.js` (4KB) ← **Caching Service Worker**
63 -
64 -## Verification Commands
65 -
66 -### Local Build Test
67 -
68 -```bash
69 -# Test Makefile
70 -make clean
71 -make build-wasm
72 -
73 -# Verify files copied
74 -ls -lh cmd/relay-server/wasm/
75 -# Should show: sw-proxy.js, sw.js
76 -
77 -# Build server
78 -make build-server
79 -
80 -# Run
81 -./bin/relayserver
82 -```
83 -
84 -### Docker Build Test
85 -
86 -```bash
87 -# Build Docker image
88 -docker build -t relaydns-server .
89 -
90 -# Run container
91 -docker run -p 4017:4017 relaydns-server
92 -
93 -# Test endpoints
94 -curl http://localhost:4017/ # Admin UI
95 -curl http://localhost:4017/sw-proxy.js # Service Worker
96 -curl http://localhost:4017/pkg/relaydns_wasm.js # WASM
97 -```
98 -
99 -### Verify Embedded Files
100 -
101 -```bash
102 -# Check if files are embedded
103 -docker run relaydns-server strings /usr/bin/relayserver | grep -E "sw-proxy"
104 -
105 -# Should output:
106 -# sw-proxy.js
107 -```
108 -
109 -## Expected HTTP Endpoints
110 -
111 -| Endpoint | File | Description |
112 -|----------|------|-------------|
113 -| `/` | Admin template | Server admin UI |
114 -| `/sw-proxy.js` | `sw-proxy.js` | E2EE proxy service worker |
115 -| `/sw.js` | `sw.js` | WASM caching service worker |
116 -| `/pkg/relaydns_wasm.js` | `relaydns_wasm.js` | WASM binding |
117 -| `/pkg/relaydns_wasm_bg.wasm` | `relaydns_wasm_bg.wasm` | WASM binary |
118 -| `/pkg/relaydns_wasm_sw.js` | `relaydns_wasm_sw.js` | SW WASM binding |
119 -| `/relay` | WebSocket handler | E2EE tunnel |
120 -| `/peer/{id}/*` | Reverse proxy | Server-side proxy |
121 -
122 -## Troubleshooting
123 -
124 -### Issue: Service Worker 404
125 -
126 -**Symptom:**
127 -```bash
128 -curl http://localhost:4017/sw-proxy.js
129 -# 404 Not Found
130 -```
131 -
132 -**Cause:** Files not copied in Makefile
133 -
134 -**Fix:**
135 -```bash
136 -# Check Makefile has these lines:
137 -make build-wasm
138 -# [wasm] copying service workers and E2EE proxy files...
139 -# cp relaydns/wasm/sw-proxy.js cmd/relay-server/wasm/
140 -# cp relaydns/wasm/sw.js cmd/relay-server/wasm/
141 -```
142 -
143 -### Issue: Files Not Embedded
144 -
145 -**Cause:** `//go:embed wasm` not working
146 -
147 -**Fix:**
148 -1. Check `view.go` has `//go:embed wasm`
149 -2. Verify files exist in `cmd/relay-server/wasm/`
150 -3. Rebuild: `go build`
151 -
152 -### Issue: Docker Build Fails
153 -
154 -**Symptom:**
155 -```
156 -Step X: cp: cannot stat 'relaydns/wasm/sw-proxy.js': No such file or directory
157 -```
158 -
159 -**Cause:** Files not committed to git
160 -
161 -**Fix:**
162 -```bash
163 -# These files MUST be committed:
164 -git add -f relaydns/wasm/sw-proxy.js
165 -git add -f relaydns/wasm/sw.js
166 -git commit -m "feat: add E2EE proxy service workers"
167 -```
168 -
169 -## Success Criteria
170 -
171 -✅ **All checks must pass:**
172 -
173 -1. **Local Build**
174 - ```bash
175 - make build
176 - ./bin/relayserver
177 - curl http://localhost:4017/sw-proxy.js | head -5
178 - # Output: // Service Worker for RelayDNS Network Proxy
179 - ```
180 -
181 -2. **Docker Build**
182 - ```bash
183 - docker build -t test .
184 - # No errors
185 - ```
186 -
187 -3. **File Size**
188 - ```bash
189 - ls -lh bin/relayserver
190 - # Should be ~18MB (includes embedded WASM)
191 - ```
192 -
193 -4. **Service Worker Registration**
194 - - Open browser: `http://localhost:4017/`
195 - - DevTools → Application → Service Workers
196 - - Should show: `sw-proxy.js` registered
197 -
198 -## Deployment Checklist
199 -
200 -- [x] Makefile updated with SW file copying
201 -- [x] `sw-proxy.js` exists in `relaydns/wasm/`
202 -- [x] `sw.js` exists in `relaydns/wasm/`
203 -- [x] `.gitignore` allows SW files to be committed
204 -- [x] `view.go` serves SW files from embed
205 -- [x] Dockerfile uses `make build-wasm`
206 -- [ ] All files committed to git
207 -- [ ] Docker image built and tested
208 -- [ ] E2EE proxy verified working
209 -
210 -## Next Steps
211 -
212 -1. **Commit Changes**
213 - ```bash
214 - git add Makefile
215 - git add relaydns/wasm/{sw-proxy.js,sw.js}
216 - git commit -m "feat: add E2EE proxy with Docker support"
217 - ```
218 -
219 -2. **Test Docker Build**
220 - ```bash
221 - docker build -t relaydns-server:latest .
222 - docker run -p 4017:4017 relaydns-server:latest
223 - ```
224 -
225 -3. **Push Image**
226 - ```bash
227 - docker tag relaydns-server:latest ghcr.io/gosuda/relaydns:latest
228 - docker push ghcr.io/gosuda/relaydns:latest
229 - ```
Dockerfile
+2
@@ -36,4 +36,6 @@ FROM gcr.io/distroless/static-debian12:nonroot
36
37 COPY --from=builder /out/relayserver /usr/bin/relayserver
38
39 +EXPOSE 4017
40 +
41 ENTRYPOINT ["/usr/bin/relayserver"]
E2EE_VERIFICATION_GUIDE.md deleted
-255
@@ -1,255 +0,0 @@
1 -# E2EE Encryption Verification Guide
2 -
3 -This guide demonstrates how to verify that the RelayDNS server acts as a **blind relay** and cannot decrypt E2EE (End-to-End Encrypted) traffic.
4 -
5 -## Overview
6 -
7 -The E2EE architecture ensures:
8 -- **Client-side encryption**: All data is encrypted in the browser using WASM
9 -- **Blind relay**: Server only forwards encrypted packets without decryption capability
10 -- **Content-Type detection**: Happens at Service Worker level before encryption
11 -
12 -## Server Logging
13 -
14 -The relay server now includes enhanced logging to show encrypted packet data as it flows through the relay. The server logs:
15 -
16 -1. **Direction**: `Client→Lease` or `Lease→Client`
17 -2. **Lease ID**: The target service identifier
18 -3. **Bytes transferred**: Size of each encrypted chunk
19 -4. **Packet count**: Number of encrypted packets relayed
20 -5. **Encrypted preview**: First 32 bytes of encrypted data in hexadecimal
21 -
22 -### Log Format
23 -
24 -```json
25 -{
26 - "level": "info",
27 - "direction": "Client→Lease",
28 - "lease_id": "ABC123XYZ",
29 - "bytes": 1024,
30 - "total_bytes": 4096,
31 - "packet_count": 4,
32 - "encrypted_preview": "a3f2e1d4c5b6a7890f1e2d3c4b5a6978...",
33 - "message": "[E2EE-RELAY] Forwarding encrypted packet (server cannot decrypt)"
34 -}
35 -```
36 -
37 -## Verification Steps
38 -
39 -### Step 1: Start the Relay Server
40 -
41 -```bash
42 -cd cmd/relay-server
43 -./relay-server
44 -
45 -# Server should start on :4017
46 -# [server] http: :4017
47 -```
48 -### Step 2: Make Test Requests
49 -
50 -In the browser console, run:
51 -
52 -```javascript
53 -// Simple text request
54 -fetch('https://api.github.com/zen')
55 - .then(r => r.text())
56 - .then(console.log);
57 -
58 -// JSON API request
59 -fetch('https://jsonplaceholder.typicode.com/posts/1')
60 - .then(r => r.json())
61 - .then(console.log);
62 -
63 -// Binary data request
64 -fetch('https://via.placeholder.com/150')
65 - .then(r => r.blob())
66 - .then(blob => console.log('Received image:', blob.size, 'bytes'));
67 -```
68 -
69 -### Step 3: Check Server Logs
70 -
71 -Watch the server console for E2EE relay logs:
72 -
73 -```bash
74 -# You should see logs like:
75 -
76 -[E2EE-RELAY] Starting E2EE tunnel relay (server acts as blind relay)
77 - lease_id=ABC123XYZ
78 -
79 -[E2EE-RELAY] Forwarding encrypted packet (server cannot decrypt)
80 - direction=Client→Lease
81 - lease_id=ABC123XYZ
82 - bytes=512
83 - total_bytes=512
84 - packet_count=1
85 - encrypted_preview=3a7f2e1d8c4b9a650f3e8d1c5b2a9746e3d8f1a4c7b2e5d9f0a3c6b8e1d4f7a2
86 -
87 -[E2EE-RELAY] Forwarding encrypted packet (server cannot decrypt)
88 - direction=Lease→Client
89 - lease_id=ABC123XYZ
90 - bytes=1024
91 - total_bytes=1536
92 - packet_count=2
93 - encrypted_preview=f9e4d3c2b1a0987654321fedcba09876543210fedcba0987654321fedcba098
94 -
95 -[E2EE-RELAY] E2EE tunnel relay completed
96 - lease_id=ABC123XYZ
97 -```
98 -
99 -## What the Logs Prove
100 -
101 -### 1. Server Cannot Decrypt
102 -
103 -The `encrypted_preview` field shows **hexadecimal gibberish**:
104 -```
105 -3a7f2e1d8c4b9a650f3e8d1c5b2a9746e3d8f1a4c7b2e5d9f0a3c6b8e1d4f7a2
106 -```
107 -
108 -This is **ChaCha20-Poly1305** encrypted data. The server:
109 -- ❌ Cannot see the HTTP headers (Host, User-Agent, etc.)
110 -- ❌ Cannot see the request method (GET, POST, etc.)
111 -- ❌ Cannot see the URL path
112 -- ❌ Cannot see the request/response body
113 -- ❌ Cannot determine if it's JSON, HTML, or binary
114 -- ✅ Can only see encrypted byte streams
115 -
116 -### 2. Blind Relay Operation
117 -
118 -The server only knows:
119 -- **Source**: Which client sent the data
120 -- **Destination**: Which lease holder should receive it
121 -- **Size**: How many bytes were transferred
122 -- **Direction**: Client→Lease or Lease→Client
123 -
124 -The server does NOT know:
125 -- What protocol is being used (HTTP, WebSocket, etc.)
126 -- What data is being transmitted
127 -- What the response contains
128 -
129 -### 3. Content-Type Detection Happens Before Encryption
130 -
131 -The Service Worker (`sw-proxy.js`) inspects `Content-Type` headers **before** passing data to WASM for encryption:
132 -
133 -```javascript
134 -// In sw-proxy.js (before encryption)
135 -const contentType = request.headers.get('content-type');
136 -if (contentType.includes('application/json')) {
137 - type = 'Text'; // or 'API'
138 -} else if (contentType.includes('multipart/form-data')) {
139 - type = 'File';
140 -}
141 -// THEN encrypt with WASM ProxyEngine
142 -```
143 -
144 -This means:
145 -- Type detection: **Client-side (unencrypted)**
146 -- Encryption: **Client-side (WASM)**
147 -- Server relay: **Blind (encrypted only)**
148 -
149 -## Comparison: Without E2EE vs With E2EE
150 -
151 -### Without E2EE (Traditional Proxy)
152 -
153 -Server log would show:
154 -```json
155 -{
156 - "method": "GET",
157 - "url": "https://api.github.com/zen",
158 - "headers": {
159 - "User-Agent": "Mozilla/5.0...",
160 - "Accept": "application/json"
161 - },
162 - "body": "...",
163 - "response_body": "Design for failure."
164 -}
165 -```
166 -
167 -### With E2EE (RelayDNS)
168 -
169 -Server log shows:
170 -```json
171 -{
172 - "direction": "Client→Lease",
173 - "encrypted_preview": "3a7f2e1d8c4b9a65...",
174 - "message": "server cannot decrypt"
175 -}
176 -```
177 -
178 -## Security Analysis
179 -
180 -### What Server CAN Do
181 -
182 -1. ✅ Count total bytes transferred
183 -2. ✅ Track connection timing (when started/ended)
184 -3. ✅ See source and destination identities (lease IDs)
185 -4. ✅ Monitor connection patterns (frequency, duration)
186 -
187 -### What Server CANNOT Do
188 -
189 -1. ❌ Decrypt any application data
190 -2. ❌ Read HTTP headers or bodies
191 -3. ❌ Modify encrypted data without detection (Poly1305 MAC)
192 -4. ❌ Perform man-in-the-middle attacks (no private keys)
193 -5. ❌ Log sensitive information (URLs, credentials, etc.)
194 -
195 -## Cryptographic Verification
196 -
197 -### Encryption Algorithm
198 -
199 -**ChaCha20-Poly1305** AEAD:
200 -- **Encryption**: ChaCha20 stream cipher (256-bit key)
201 -- **Authentication**: Poly1305 MAC (128-bit tag)
202 -- **Nonce**: 12 bytes random per message
203 -
204 -### Key Exchange
205 -
206 -**X25519** ephemeral key exchange:
207 -- Fresh keys per connection
208 -- No long-term keys stored on server
209 -- Perfect forward secrecy
210 -
211 -### Signature Verification
212 -
213 -**Ed25519** signatures:
214 -- Identity authentication
215 -- Cannot forge without private key
216 -- Server only verifies signatures, cannot decrypt
217 -
218 -## Testing Encrypted Data
219 -
220 -You can verify encryption by:
221 -
222 -1. **Inspect Network Tab** (browser):
223 - - Open DevTools → Network
224 - - Filter: WS (WebSocket)
225 - - Click on `/relay` connection
226 - - View Messages tab
227 - - You'll see binary frames (encrypted)
228 -
229 -2. **Server Logs**:
230 - - Look for `[E2EE-RELAY]` messages
231 - - `encrypted_preview` should be random hex
232 - - No plaintext should appear
233 -
234 -3. **Wireshark/tcpdump** (advanced):
235 - - Capture WebSocket traffic
236 - - All application data appears as binary blobs
237 - - No HTTP headers/bodies visible in relay tunnel
238 -
239 -## Conclusion
240 -
241 -The server logs **prove** that:
242 -
243 -1. ✅ All data is encrypted before reaching the server
244 -2. ✅ Server acts as a blind relay (cannot decrypt)
245 -3. ✅ Content-Type detection happens client-side before encryption
246 -4. ✅ E2EE architecture is working as designed
247 -
248 -The relay server is **zero-knowledge** about application content, ensuring maximum privacy and security for all relayed communications.
249 -
250 -## Further Reading
251 -
252 -- [E2EE_PROXY_INTEGRATION.md](relaydns/wasm/E2EE_PROXY_INTEGRATION.md) - Integration guide
253 -- [E2EE_PROXY_DEPLOYMENT.md](E2EE_PROXY_DEPLOYMENT.md) - Deployment guide (Korean)
254 -- [relaydns/core/cryptoops/README.md](relaydns/core/cryptoops/README.md) - Cryptographic details
255 -- [SERVICE_WORKER.md](relaydns/wasm/SERVICE_WORKER.md) - Service Worker implementation