Add tailscale_enable_funnel_to_localhost_plaintext_http1 to tailscale.h

This commit is contained in:
Yagil Burowski
2025-01-20 00:35:58 -05:00
committed by Brad Fitzpatrick
parent 75f9bc2786
commit 9d45e587f0
3 changed files with 64 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ extern int TsnetGetIps(int sd, char *buf, size_t buflen);
extern int TsnetGetRemoteAddr(int listener, int conn, char *buf, size_t buflen);
extern int TsnetListen(int sd, char* net, char* addr, int* listenerOut);
extern int TsnetLoopback(int sd, char* addrOut, size_t addrLen, char* proxyOut, char* localOut);
extern int TsnetEnableFunnelToLocalhostPlaintextHttp1(int sd, int localhostPort);
tailscale tailscale_new() {
return TsnetNewServer();
@@ -106,3 +107,7 @@ int tailscale_loopback(tailscale sd, char* addr_out, size_t addrlen, char* proxy
int tailscale_errmsg(tailscale sd, char* buf, size_t buflen) {
return TsnetErrmsg(sd, buf, buflen);
}
int tailscale_enable_funnel_to_localhost_plaintext_http1(tailscale sd, int localhostPort) {
return TsnetEnableFunnelToLocalhostPlaintextHttp1(sd, localhostPort);
}

View File

@@ -14,12 +14,14 @@ import (
"net"
"os"
"regexp"
"strconv"
"strings"
"sync"
"syscall"
"unsafe"
"tailscale.com/hostinfo"
"tailscale.com/ipn"
"tailscale.com/tsnet"
"tailscale.com/types/logger"
)
@@ -531,3 +533,44 @@ func TsnetLoopback(sd C.int, addrOut *C.char, addrLen C.size_t, proxyOut *C.char
return 0
}
//export TsnetEnableFunnelToLocalhostPlaintextHttp1
func TsnetEnableFunnelToLocalhostPlaintextHttp1(sd C.int, localhostPort C.int) C.int {
s, err := getServer(sd)
if err != nil {
return s.recErr(err)
}
ctx := context.Background()
lc, err := s.s.LocalClient()
if err != nil {
return s.recErr(err)
}
st, err := lc.StatusWithoutPeers(ctx)
if err != nil {
return s.recErr(err)
}
domain := st.CertDomains[0]
hp := ipn.HostPort(net.JoinHostPort(domain, strconv.Itoa(443)))
tcpForward := fmt.Sprintf("127.0.0.1:%d", localhostPort)
sc := &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{
443: {
TCPForward: tcpForward,
TerminateTLS: domain,
},
},
AllowFunnel: map[ipn.HostPort]bool{
hp: true,
},
}
lc.SetServeConfig(ctx, sc)
if !sc.AllowFunnel[hp] {
return s.recErr(fmt.Errorf("libtailscale: failed to enable funnel"))
}
return 0
}

View File

@@ -175,6 +175,22 @@ extern int tailscale_accept(tailscale_listener listener, tailscale_conn* conn_ou
// Returns zero on success or -1 on error, call tailscale_errmsg for details.
extern int tailscale_loopback(tailscale sd, char* addr_out, size_t addrlen, char* proxy_cred_out, char* local_api_cred_out);
// tailscale_enable_funnel_to_localhost_plaintext_http1 configures sd to have
// Tailscale Funnel enabled, routing requests from the public web
// (without any authentication) down to this Tailscale node, requesting new
// LetsEncrypt TLS certs as needed, terminating TLS, and proxying all incoming
// HTTPS requests to http://127.0.0.1:localhostPort without TLS.
//
// There should be a plaintext HTTP/1 server listening on 127.0.0.1:localhostPort
// or tsnet will serve HTTP 502 errors.
//
// Expect junk traffic from the internet from bots watching the public CT logs.
//
// Returns:
// 0 - success
// -1 - other error, details printed to the tsnet logger
extern int tailscale_enable_funnel_to_localhost_plaintext_http1(tailscale sd, int localhostPort);
// tailscale_errmsg writes the details of the last error to buf.
//
// After returning, buf is always NUL-terminated.