|
|
@ -6,6 +6,8 @@ import ( |
|
|
"crypto/rand" |
|
|
"crypto/rand" |
|
|
"crypto/tls" |
|
|
"crypto/tls" |
|
|
"errors" |
|
|
"errors" |
|
|
|
|
|
"fmt" |
|
|
|
|
|
"io/ioutil" |
|
|
"net/http" |
|
|
"net/http" |
|
|
"net/http/httptest" |
|
|
"net/http/httptest" |
|
|
"net/url" |
|
|
"net/url" |
|
|
@ -18,18 +20,21 @@ func sniRoundtrip(client *Client, server *Server, targetURL string, data []byte) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
defer conn.Close() |
|
|
|
|
|
|
|
|
|
|
|
conn.SetDeadline(time.Now().Add(3 * time.Second)) |
|
|
|
|
|
|
|
|
|
|
|
conn, err = client.Handshake(conn) |
|
|
conn, err = client.Handshake(conn, AddrHandshakeOption(server.Addr().String())) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
defer conn.Close() |
|
|
|
|
|
|
|
|
u, err := url.Parse(targetURL) |
|
|
u, err := url.Parse(targetURL) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
conn.SetDeadline(time.Now().Add(3 * time.Second)) |
|
|
|
|
|
defer conn.SetDeadline(time.Time{}) |
|
|
|
|
|
|
|
|
conn, err = client.Connect(conn, u.Host) |
|
|
conn, err = client.Connect(conn, u.Host) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return |
|
|
return |
|
|
@ -38,8 +43,8 @@ func sniRoundtrip(client *Client, server *Server, targetURL string, data []byte) |
|
|
if u.Scheme == "https" { |
|
|
if u.Scheme == "https" { |
|
|
conn = tls.Client(conn, |
|
|
conn = tls.Client(conn, |
|
|
&tls.Config{ |
|
|
&tls.Config{ |
|
|
InsecureSkipVerify: false, |
|
|
InsecureSkipVerify: true, |
|
|
ServerName: u.Hostname(), |
|
|
// ServerName: u.Hostname(),
|
|
|
}) |
|
|
}) |
|
|
u.Scheme = "http" |
|
|
u.Scheme = "http" |
|
|
} |
|
|
} |
|
|
@ -64,6 +69,15 @@ func sniRoundtrip(client *Client, server *Server, targetURL string, data []byte) |
|
|
return errors.New(resp.Status) |
|
|
return errors.New(resp.Status) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
recv, err := ioutil.ReadAll(resp.Body) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !bytes.Equal(data, recv) { |
|
|
|
|
|
return fmt.Errorf("data not equal") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -73,6 +87,11 @@ func sniProxyRoundtrip(targetURL string, data []byte, host string) error { |
|
|
return err |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
u, err := url.Parse(targetURL) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
client := &Client{ |
|
|
client := &Client{ |
|
|
Connector: SNIConnector(host), |
|
|
Connector: SNIConnector(host), |
|
|
Transporter: TCPTransporter(), |
|
|
Transporter: TCPTransporter(), |
|
|
@ -80,7 +99,7 @@ func sniProxyRoundtrip(targetURL string, data []byte, host string) error { |
|
|
|
|
|
|
|
|
server := &Server{ |
|
|
server := &Server{ |
|
|
Listener: ln, |
|
|
Listener: ln, |
|
|
Handler: SNIHandler(), |
|
|
Handler: SNIHandler(HostHandlerOption(u.Host)), |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
go server.Run() |
|
|
go server.Run() |
|
|
@ -90,19 +109,40 @@ func sniProxyRoundtrip(targetURL string, data []byte, host string) error { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func TestSNIProxy(t *testing.T) { |
|
|
func TestSNIProxy(t *testing.T) { |
|
|
httpSrv := httptest.NewTLSServer(httpTestHandler) |
|
|
httpSrv := httptest.NewServer(httpTestHandler) |
|
|
defer httpSrv.Close() |
|
|
defer httpSrv.Close() |
|
|
|
|
|
|
|
|
|
|
|
httpsSrv := httptest.NewTLSServer(httpTestHandler) |
|
|
|
|
|
defer httpsSrv.Close() |
|
|
|
|
|
|
|
|
sendData := make([]byte, 128) |
|
|
sendData := make([]byte, 128) |
|
|
rand.Read(sendData) |
|
|
rand.Read(sendData) |
|
|
|
|
|
|
|
|
err := sniProxyRoundtrip("https://github.com", sendData, "") |
|
|
var sniProxyTests = []struct { |
|
|
if err != nil { |
|
|
targetURL string |
|
|
t.Errorf("got error: %v", err) |
|
|
host string |
|
|
|
|
|
pass bool |
|
|
|
|
|
}{ |
|
|
|
|
|
{httpSrv.URL, "", true}, |
|
|
|
|
|
{httpSrv.URL, "example.com", true}, |
|
|
|
|
|
{httpsSrv.URL, "", true}, |
|
|
|
|
|
{httpsSrv.URL, "example.com", true}, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
err = sniProxyRoundtrip("https://github.com", sendData, "google.com") |
|
|
for i, tc := range sniProxyTests { |
|
|
if err != nil { |
|
|
tc := tc |
|
|
t.Errorf("got error: %v", err) |
|
|
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { |
|
|
|
|
|
err := sniProxyRoundtrip(tc.targetURL, sendData, tc.host) |
|
|
|
|
|
if err == nil { |
|
|
|
|
|
if !tc.pass { |
|
|
|
|
|
t.Errorf("#%d should failed", i) |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// t.Logf("#%d %v", i, err)
|
|
|
|
|
|
if tc.pass { |
|
|
|
|
|
t.Errorf("#%d got error: %v", i, err) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|