traffic to deadshadow passes through an offshore gre tunnel before reaching our server. the gre endpoint forwards requests without preserving the original public source ip: nginx sees only an internal tunnel address (10.10.10.x) as $remote_addr. nginx then rewrites x-forwarded-for to 0.0.0.0 before passing to synapse. the verification below uses a nonce to confirm both layers are working and that your real ip does not appear at either point in the chain.
remote_addr_nginx is 10.10.10.x — the internal gre tunnel address. your real ip does not appear anywhere in this response. your nonce appears in incoming_x_proof_nonce, confirming this is a live response and not cached output.
headers.X-Forwarded-For is 0.0.0.0. your nonce still appears in headers.X-Proof-Nonce, confirming your real ip does not appear at the upstream either.
add these blocks inside your tls server { }. /proof/raw returns what nginx directly received. /proof/upstream forwards to the local echo service with x-forwarded-for forced to 0.0.0.0.
# /proof/raw — what NGINX receives from the GRE tunnel
location = /proof/raw {
default_type application/json;
add_header Cache-Control "no-store" always;
return 200
'{
"remote_addr_nginx": "$remote_addr",
"incoming_x_forwarded_for": "$http_x_forwarded_for",
"incoming_x_proof_nonce": "$http_x_proof_nonce",
"host": "$host",
"scheme": "$scheme"
}';
}
# /proof/upstream — what a separate upstream app receives
location = /proof/upstream {
proxy_pass http://127.0.0.1:18010/;
proxy_set_header X-Forwarded-For 0.0.0.0;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
}
sudo nginx -t && sudo systemctl reload nginx
bound to 127.0.0.1:18010. returns received headers as json. logging is disabled. operates independently from nginx.
# /opt/deadshadow/proof-echo.py
#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/":
self.send_response(404); self.end_headers(); return
payload = {
"client_addr_seen_by_app": self.client_address[0],
"method": self.command,
"path": self.path,
"headers": {k: v for k, v in self.headers.items()},
}
body = (json.dumps(payload, indent=2, sort_keys=True) + "\n").encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Cache-Control", "no-store")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
return
HTTPServer(("127.0.0.1", 18010), Handler).serve_forever()
# /etc/systemd/system/deadshadow-proof-echo.service
[Unit]
Description=Deadshadow proof echo upstream
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/deadshadow/proof-echo.py
User=nobody
Group=nogroup
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now deadshadow-proof-echo