Add BWH US DC1 proxy stack

This commit is contained in:
Codex
2026-09-03 01:52:58 -07:00
parent a922793499
commit 108e5d8021
9 changed files with 316 additions and 0 deletions
@@ -0,0 +1,2 @@
# HAProxy owns public TCP 443. Hysteria2 owns public UDP 443 separately.
HAPROXY_PUBLIC_PORT=443
+12
View File
@@ -0,0 +1,12 @@
# DC1 TLS front door
HAProxy inspects TCP SNI without terminating TLS:
- `dc1-tls-676b11.opfo.xyz` -> sing-box Trojan on internal TCP 34795
- `dc1-any-9a4fad.opfo.xyz` -> sing-box AnyTLS on internal TCP 40887
- unmatched SNI -> Caddy fallback serving `dc1.opfo.xyz`
HAProxy publishes host TCP 443. Hysteria2 owns host UDP 443. Caddy publishes
host TCP 80 and receives HTTPS from HAProxy over the project network. Trojan
and AnyTLS have no high-numbered host port. Both projects join the external
`dc1-proxy` network.
@@ -0,0 +1,22 @@
{
email tnki.per@gmail.com
servers {
protocols h1 h2
}
}
dc1.opfo.xyz {
encode zstd gzip
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy no-referrer
}
respond <<HTML
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Service Status</title></head>
<body><main><h1>Service online</h1><p>The requested service is available.</p></main></body>
</html>
HTML
}
+44
View File
@@ -0,0 +1,44 @@
services:
haproxy:
image: haproxy:3.4.4-alpine3.24
container_name: dc1-haproxy
restart: unless-stopped
ports:
- "${HAPROXY_PUBLIC_PORT:-443}:8443/tcp"
depends_on:
- decoy-caddy
networks:
- default
- proxy
volumes:
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
logging:
driver: json-file
options:
max-size: 200k
max-file: "2"
decoy-caddy:
image: caddy:2.11.4
container_name: dc1-decoy-caddy
restart: unless-stopped
ports:
- "80:80/tcp"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
logging:
driver: json-file
options:
max-size: 200k
max-file: "2"
volumes:
caddy-data:
caddy-config:
networks:
proxy:
external: true
name: dc1-proxy
@@ -0,0 +1,32 @@
global
log stdout format raw local0
maxconn 4096
defaults
log global
mode tcp
option tcplog
timeout connect 5s
timeout client 24h
timeout server 24h
frontend tls_443
bind 0.0.0.0:8443
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
acl sni_trojan req.ssl_sni -i dc1-tls-676b11.opfo.xyz
acl sni_anytls req.ssl_sni -i dc1-any-9a4fad.opfo.xyz
use_backend singbox_trojan if sni_trojan
use_backend singbox_anytls if sni_anytls
default_backend decoy_https
backend singbox_trojan
server trojan dc1-sing-box:34795
backend singbox_anytls
server anytls dc1-sing-box:40887
backend decoy_https
server caddy decoy-caddy:443
+18
View File
@@ -0,0 +1,18 @@
DOMAIN=dc1-tls-676b11.opfo.xyz
ACME_EMAIL=admin@example.com
LISTEN_PORT=34795
USER1_PASSWORD=change-me
CLOUDFLARE_API_TOKEN=change-me
ANYTLS_DOMAIN=dc1-any-9a4fad.opfo.xyz
ANYTLS_PORT=40887
ANYTLS_PASSWORD=change-me
HY2_PASSWORD=change-me
HY2_OBFS_PASSWORD=change-me
HY2_PORT=443
# sing-box uses version 5 for the Snell v4-compatible TCP wire protocol.
SNELL_V4_PORT=31385
SNELL_V4_PSK=change-me
SNELL_V6_PORT=27276
SNELL_V6_PSK=change-me-at-least-12-bytes
+15
View File
@@ -0,0 +1,15 @@
# DC1 sing-box
The managed sing-box service provides:
- Trojan on internal TCP 34795, exposed only on TCP 443 through HAProxy
- AnyTLS on internal TCP 40887, exposed only on TCP 443 through HAProxy
- Hysteria2 on UDP 443
- Snell v4-compatible on TCP 31385 (`version: 5` server wire format)
- Snell v6 on TCP 27276
Credentials and the Cloudflare API token live only in the Arcane
Environment-local `.env`. Reality is intentionally omitted because it did not
pass repeat interoperability tests on the existing HK and DC9 nodes. The ACME
provider is ZeroSSL; sing-box automatically obtains ZeroSSL EAB credentials
from the configured account email.
+62
View File
@@ -0,0 +1,62 @@
services:
config-render:
image: alpine:3.24
environment:
DOMAIN: ${DOMAIN}
ACME_EMAIL: ${ACME_EMAIL}
LISTEN_PORT: ${LISTEN_PORT}
USER1_PASSWORD: ${USER1_PASSWORD}
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
ANYTLS_DOMAIN: ${ANYTLS_DOMAIN}
ANYTLS_PORT: ${ANYTLS_PORT}
ANYTLS_PASSWORD: ${ANYTLS_PASSWORD}
HY2_PASSWORD: ${HY2_PASSWORD}
HY2_OBFS_PASSWORD: ${HY2_OBFS_PASSWORD}
HY2_PORT: ${HY2_PORT}
SNELL_V4_PORT: ${SNELL_V4_PORT}
SNELL_V4_PSK: ${SNELL_V4_PSK}
SNELL_V6_PORT: ${SNELL_V6_PORT}
SNELL_V6_PSK: ${SNELL_V6_PSK}
volumes:
- ./etc/sing-box/config.json.template:/template/config.json.template:ro
- sing-box-config:/output
command:
- /bin/sh
- -ec
- |
apk add --no-cache gettext
envsubst < /template/config.json.template > /output/config.json
chmod 600 /output/config.json
restart: "no"
sing-box:
image: ghcr.io/sagernet/sing-box:v1.14.0
container_name: dc1-sing-box
restart: unless-stopped
depends_on:
config-render:
condition: service_completed_successfully
volumes:
- sing-box-config:/etc/sing-box:ro
- sing-box-data:/var/lib/sing-box
command: -D /var/lib/sing-box -C /etc/sing-box/ run
ports:
- "443:443/udp"
- "31385:31385/tcp"
- "27276:27276/tcp"
networks:
- proxy
logging:
driver: json-file
options:
max-size: 200k
max-file: "2"
volumes:
sing-box-config:
sing-box-data:
networks:
proxy:
external: true
name: dc1-proxy
@@ -0,0 +1,109 @@
{
"certificate_providers": [
{
"type": "acme",
"tag": "public-cert",
"provider": "zerossl",
"domain": [
"${DOMAIN}",
"${ANYTLS_DOMAIN}"
],
"email": "${ACME_EMAIL}",
"dns01_challenge": {
"provider": "cloudflare",
"api_token": "${CLOUDFLARE_API_TOKEN}"
}
}
],
"inbounds": [
{
"type": "trojan",
"tag": "trojan-in",
"listen": "::",
"listen_port": ${LISTEN_PORT},
"users": [
{
"name": "user1",
"password": "${USER1_PASSWORD}"
}
],
"tls": {
"enabled": true,
"server_name": "${DOMAIN}",
"certificate_provider": "public-cert"
},
"multiplex": {
"enabled": true
}
},
{
"type": "anytls",
"tag": "anytls-in",
"listen": "::",
"listen_port": ${ANYTLS_PORT},
"users": [
{
"name": "user1",
"password": "${ANYTLS_PASSWORD}"
}
],
"tls": {
"enabled": true,
"server_name": "${ANYTLS_DOMAIN}",
"certificate_provider": "public-cert"
}
},
{
"type": "hysteria2",
"tag": "hysteria2-in",
"listen": "0.0.0.0",
"listen_port": ${HY2_PORT},
"obfs": {
"type": "salamander",
"password": "${HY2_OBFS_PASSWORD}"
},
"users": [
{
"name": "user1",
"password": "${HY2_PASSWORD}"
}
],
"tls": {
"enabled": true,
"server_name": "${ANYTLS_DOMAIN}",
"alpn": [
"h3"
],
"certificate_provider": "public-cert"
}
},
{
"type": "snell",
"tag": "snell-v4-compatible-in",
"listen": "::",
"listen_port": ${SNELL_V4_PORT},
"version": 5,
"psk": "${SNELL_V4_PSK}",
"obfs_mode": "none"
},
{
"type": "snell",
"tag": "snell-v6-in",
"listen": "::",
"listen_port": ${SNELL_V6_PORT},
"version": 6,
"psk": "${SNELL_V6_PSK}",
"mode": "default"
}
],
"outbounds": [
{
"type": "direct"
}
],
"log": {
"disabled": false,
"level": "info",
"timestamp": true
}
}