feat: add TLS mode toggle and update command generation for tunnel
gosunuts committed
Feb 26, 2026 at 13:55 UTC
9f5041e4a41f8b5056f6b666e1ec8b5512645df7
2 files changed
+41
-18
cmd/portal-tunnel/main.go
+15
-15
@@ -95,18 +95,18 @@ func runServiceTunnel(ctx context.Context, relayURLs []string) error {
95
return fmt.Errorf("no relay URLs provided")
96
}
97
98
- log.Info().Str("service", flagName).Msgf("Local service is reachable at %s", flagHost)
99
- log.Info().Str("service", flagName).Msg("Starting Portal Tunnel...")
100
- log.Info().Str("service", flagName).Msgf(" Local: %s", flagHost)
101
- log.Info().Str("service", flagName).Msgf(" Relays: %s", strings.Join(relayURLs, ", "))
102
- log.Info().Str("service", flagName).Msgf(" TLS Mode: %v", flagTLSEnable)
98
+ log.Info().Msgf("Local service is reachable at %s", flagHost)
99
+ log.Info().Msg("Starting Portal Tunnel...")
100
+ log.Info().Msgf(" Local: %s", flagHost)
101
+ log.Info().Msgf(" Relays: %s", strings.Join(relayURLs, ", "))
102
+ log.Info().Msgf(" TLS Mode: %v", flagTLSEnable)
103
104
var clientOpts []sdk.ClientOption
105
clientOpts = append(clientOpts, sdk.WithBootstrapServers(relayURLs))
106
107
if flagTLSEnable {
108
clientOpts = append(clientOpts, sdk.WithTLS())
109
- log.Info().Str("service", flagName).Msg("TLS: Using relay ACME DNS-01 (E2EE)")
109
+ log.Info().Msg("TLS: Using relay ACME DNS-01 (E2EE)")
110
}
111
112
client, err := sdk.NewClient(clientOpts...)
@@ -134,14 +134,14 @@ func runServiceTunnel(ctx context.Context, relayURLs []string) error {
134
_ = listener.Close()
135
}()
136
137
- log.Info().Str("service", flagName).Msg("")
138
- log.Info().Str("service", flagName).Msg("Access via:")
139
- log.Info().Str("service", flagName).Msgf("- Relay: %s", relayURLs[0])
137
+ log.Info().Msg("")
138
+ log.Info().Msg("Access via:")
139
+ log.Info().Msgf("- Relay: %s", relayURLs[0])
140
if leaseAware, ok := listener.(interface{ LeaseID() string }); ok {
141
- log.Info().Str("service", flagName).Msgf("- Lease ID: %s", leaseAware.LeaseID())
141
+ log.Info().Msgf("- Lease ID: %s", leaseAware.LeaseID())
142
}
143
if flagTLSEnable {
144
- log.Info().Str("service", flagName).Msg("- TLS: Enabled")
144
+ log.Info().Msg("- TLS: Enabled")
145
}
146
147
log.Info().Str("service", flagName).Msg("")
@@ -162,13 +162,13 @@ func runServiceTunnel(ctx context.Context, relayURLs []string) error {
162
case <-ctx.Done():
163
return nil
164
default:
165
- log.Error().Str("service", flagName).Err(err).Msg("Failed to accept connection")
165
+ log.Error().Err(err).Msg("Failed to accept connection")
166
continue
167
}
168
}
169
170
connCount++
171
- log.Info().Str("service", flagName).Msgf("→ [#%d] New connection from %s", connCount, relayConn.RemoteAddr())
171
+ log.Info().Msgf("→ [#%d] New connection from %s", connCount, relayConn.RemoteAddr())
172
173
connWG.Add(1)
174
go func(relayConn net.Conn) {
@@ -178,9 +178,9 @@ func runServiceTunnel(ctx context.Context, relayURLs []string) error {
178
proxyType = "TLS→TCP"
179
}
180
if err := proxyConnection(ctx, flagHost, relayConn, flagTLSEnable); err != nil {
181
- log.Error().Str("service", flagName).Str("proxy", proxyType).Err(err).Msg("Proxy error")
181
+ log.Error().Str("proxy", proxyType).Err(err).Msg("Proxy error")
182
}
183
- log.Info().Str("service", flagName).Str("proxy", proxyType).Msg("Connection closed")
183
+ log.Info().Str("proxy", proxyType).Msg("Connection closed")
184
}(relayConn)
185
}
186
}
cmd/relay-server/frontend/src/components/TunnelCommandModal.tsx
+26
-3
@@ -34,6 +34,7 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
34
const [urlInput, setUrlInput] = useState("");
35
const [copied, setCopied] = useState(false);
36
const [os, setOs] = useState<"unix" | "windows">("unix");
37
+ const [tlsEnabled, setTlsEnabled] = useState(true);
38
const urlInputRef = useRef<HTMLInputElement>(null);
39
40
const addRelayUrl = (url: string) => {
@@ -75,11 +76,13 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
76
relayUrls.length > 0 ? relayUrls.join(",") : currentOrigin;
77
78
if (os === "windows") {
78
- return `$ProgressPreference = 'SilentlyContinue'; $env:HOST="${hostVal}"; $env:NAME="${nameVal}"; $env:RELAY_URL="${relayUrlVal}"; irm ${currentOrigin}/tunnel?os=windows | iex`;
79
+ const tlsEnv = tlsEnabled ? "" : "$env:TLS=\"false\"; ";
80
+ return `$ProgressPreference = 'SilentlyContinue'; ${tlsEnv}$env:HOST="${hostVal}"; $env:NAME="${nameVal}"; $env:RELAY_URL="${relayUrlVal}"; irm ${currentOrigin}/tunnel?os=windows | iex`;
81
}
82
81
- return `curl -fsSL ${currentOrigin}/tunnel | HOST=${hostVal} NAME=${nameVal} RELAY_URL="${relayUrlVal}" sh`;
82
- }, [currentOrigin, host, name, relayUrls, os]);
83
+ const tlsEnv = tlsEnabled ? "" : "TLS=false ";
84
+ return `curl -fsSL ${currentOrigin}/tunnel | ${tlsEnv}HOST=${hostVal} NAME=${nameVal} RELAY_URL="${relayUrlVal}" sh`;
85
+ }, [currentOrigin, host, name, relayUrls, os, tlsEnabled]);
86
87
const handleCopy = async () => {
88
try {
@@ -229,6 +232,26 @@ export function TunnelCommandModal({ trigger }: TunnelCommandModalProps) {
232
</div>
233
</div>
234
235
+ {/* TLS Mode */}
236
+ <div className="space-y-2">
237
+ <label className="flex items-center gap-2 cursor-pointer">
238
+ <input
239
+ type="checkbox"
240
+ checked={tlsEnabled}
241
+ onChange={(e) => setTlsEnabled(e.target.checked)}
242
+ className="w-4 h-4 rounded border-input cursor-pointer"
243
+ />
244
+ <span className="text-sm font-medium text-foreground">
245
+ TLS Mode (End-to-End Encryption)
246
+ </span>
247
+ </label>
248
+ <p className="text-xs text-text-muted">
249
+ {tlsEnabled
250
+ ? "End-to-end encryption with relay ACME DNS-01 certificates"
251
+ : "HTTP proxy mode without TLS termination"}
252
+ </p>
253
+ </div>
254
+
255
{/* Generated Command */}
256
<div className="space-y-2">
257
<label className="text-sm font-medium text-foreground">