package shadow import ( "crypto/tls" "fmt" "io" "net" "time" ) type Client struct { ListenAddress string ServerAddress string FakeAddressSNI string } func NewClient(listenAddress string, serverAddress string, fakeAddressSNI string) *Client { client := &Client{ ListenAddress: listenAddress, ServerAddress: serverAddress, FakeAddressSNI: fakeAddressSNI, } return client } func (c *Client) Start() { listen, err := net.Listen("tcp", c.ListenAddress) if err != nil { fmt.Printf("[Client] Start client error: %v\n", err) return } defer listen.Close() fmt.Printf("[Client] Listening at:%v\n", c.ListenAddress) for { conn, err := listen.Accept() if err != nil { fmt.Printf("[Client] accept error: %v\n", err) continue } go handlerClient(conn, c.ServerAddress, c.FakeAddressSNI) } } func handlerClient(conn net.Conn, serverAddress string, fakeAddressSNI string) { dial, err := tls.DialWithDialer(&net.Dialer{ Timeout: time.Second * 5, }, "tcp", serverAddress, &tls.Config{ ServerName: fakeAddressSNI, }) if err != nil { fmt.Printf("[Client] Dial server error: %v\n", err) return } err = dial.Handshake() if err != nil { fmt.Printf("[Client] Handshake error: %v\n", err) return } dial.NetConn().SetDeadline(time.Now()) dial.NetConn().SetDeadline(time.Time{}) go io.Copy(conn, dial.NetConn()) go io.Copy(dial.NetConn(), conn) }