From 508c4293d594735b67caaa5ad944374062b7af23 Mon Sep 17 00:00:00 2001 From: ooninoob Date: Wed, 23 Nov 2022 10:56:06 +0100 Subject: [PATCH] Add -tls-proxy-outbound-port flag to jafar (useful for non-HTTPS protocols) Edit README to make it explicit that tlsproxy has nothing to do with HTTP and can be used with any TCP protocol that does TLS handshakes. --- internal/cmd/jafar/README.md | 8 +++++--- internal/cmd/jafar/main.go | 13 +++++++++---- internal/cmd/jafar/tlsproxy/tlsproxy.go | 14 ++++++++++---- internal/cmd/jafar/tlsproxy/tlsproxy_test.go | 4 ++-- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/internal/cmd/jafar/README.md b/internal/cmd/jafar/README.md index 8b4722a..a769753 100644 --- a/internal/cmd/jafar/README.md +++ b/internal/cmd/jafar/README.md @@ -156,14 +156,16 @@ response for every request whose `Host` contains the specified string. ### tls-proxy -TLS proxy is a proxy that routes traffic to specific servers depending +TLS proxy is a TCP proxy that routes traffic to specific servers depending on their SNI value. It is controlled by the following flags: ```bash -tls-proxy-address string - Address where the HTTP proxy should listen (default "127.0.0.1:443") + Address where the TCP+TLS proxy should listen (default "127.0.0.1:443") -tls-proxy-block value - Register keyword triggering TLS censorship + Register SNI header keyword triggering TLS censorship + -tls-proxy-outbound-port + Define the outbound port requests are proxied to (default "443 for HTTPS) ``` The `-tls-proxy-address` flags has the same semantics it has for the DNS diff --git a/internal/cmd/jafar/main.go b/internal/cmd/jafar/main.go index 61f5285..7d376d8 100644 --- a/internal/cmd/jafar/main.go +++ b/internal/cmd/jafar/main.go @@ -58,8 +58,9 @@ var ( tag *string - tlsProxyAddress *string - tlsProxyBlock flagx.StringArray + tlsProxyAddress *string + tlsProxyBlock flagx.StringArray + tlsProxyOutboundPort *string uncensoredResolverDoH *string ) @@ -159,12 +160,16 @@ func init() { // tlsProxy tlsProxyAddress = flag.String( "tls-proxy-address", "127.0.0.1:443", - "Address where the HTTP proxy should listen", + "Address where the TCP+TLS proxy should listen", ) flag.Var( &tlsProxyBlock, "tls-proxy-block", "Register keyword triggering TLS censorship", ) + tlsProxyOutboundPort = flag.String( + "tls-proxy-outbound-port", "443", + "The outbound port where requests should be proxied", + ) // uncensored uncensoredResolverDoH = flag.String( @@ -227,7 +232,7 @@ func iptablesStart() *iptables.CensoringPolicy { } func tlsProxyStart(uncensored *uncensored.Client) net.Listener { - proxy := tlsproxy.NewCensoringProxy(tlsProxyBlock, uncensored) + proxy := tlsproxy.NewCensoringProxy(tlsProxyBlock, uncensored, tlsProxyOutboundPort) listener, err := proxy.Start(*tlsProxyAddress) runtimex.PanicOnError(err, "proxy.Start failed") return listener diff --git a/internal/cmd/jafar/tlsproxy/tlsproxy.go b/internal/cmd/jafar/tlsproxy/tlsproxy.go index 91cede5..d98751f 100644 --- a/internal/cmd/jafar/tlsproxy/tlsproxy.go +++ b/internal/cmd/jafar/tlsproxy/tlsproxy.go @@ -21,8 +21,9 @@ type Dialer interface { // CensoringProxy is a censoring TLS proxy type CensoringProxy struct { - keywords []string - dial func(network, address string) (net.Conn, error) + keywords []string + dial func(network, address string) (net.Conn, error) + outboundPort string } // NewCensoringProxy creates a new CensoringProxy instance using @@ -31,13 +32,18 @@ type CensoringProxy struct { // the SNII record of a ClientHello. dnsNetwork and dnsAddress are // settings to configure the upstream, non censored DNS. func NewCensoringProxy( - keywords []string, uncensored Dialer, + keywords []string, uncensored Dialer, outboundPort *string, ) *CensoringProxy { + defaultPort := "443" + if outboundPort == nil { + outboundPort = &defaultPort + } return &CensoringProxy{ keywords: keywords, dial: func(network, address string) (net.Conn, error) { return uncensored.DialContext(context.Background(), network, address) }, + outboundPort: *outboundPort, } } @@ -146,7 +152,7 @@ func (p *CensoringProxy) handle(clientconn net.Conn) { return } } - serverconn, err := p.dial("tcp", net.JoinHostPort(sni, "443")) + serverconn, err := p.dial("tcp", net.JoinHostPort(sni, p.outboundPort)) if err != nil { log.WithError(err).Warn("tlsproxy: p.dial failed") alertclose(clientconn) diff --git a/internal/cmd/jafar/tlsproxy/tlsproxy_test.go b/internal/cmd/jafar/tlsproxy/tlsproxy_test.go index 86a21d8..1394ba6 100644 --- a/internal/cmd/jafar/tlsproxy/tlsproxy_test.go +++ b/internal/cmd/jafar/tlsproxy/tlsproxy_test.go @@ -94,7 +94,7 @@ func TestFailWriteAfterConnect(t *testing.T) { func TestListenError(t *testing.T) { proxy := NewCensoringProxy( - []string{""}, uncensored.NewClient("https://1.1.1.1/dns-query"), + []string{""}, uncensored.NewClient("https://1.1.1.1/dns-query"), nil, ) listener, err := proxy.Start("8.8.8.8:80") if err == nil { @@ -107,7 +107,7 @@ func TestListenError(t *testing.T) { func newproxy(t *testing.T, blocked string) net.Listener { proxy := NewCensoringProxy( - []string{blocked}, uncensored.NewClient("https://1.1.1.1/dns-query"), + []string{blocked}, uncensored.NewClient("https://1.1.1.1/dns-query"), nil, ) listener, err := proxy.Start("127.0.0.1:0") if err != nil {