Created
January 11, 2021 09:11
-
-
Save mwpcheung/8a62dea70262d9705e6cefea2a7953da to your computer and use it in GitHub Desktop.
connect tls server with socks/https proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"bytes" | |
"crypto/tls" | |
"encoding/base64" | |
"encoding/hex" | |
"fmt" | |
"log" | |
"net" | |
"net/http" | |
"net/url" | |
"strings" | |
"time" | |
"golang.org/x/net/proxy" | |
) | |
func dialProxy(sproxy, hostport string) (net.Conn, error) { | |
u, _ := url.Parse(sproxy) | |
switch u.Scheme { | |
case "socks5", "socks5h": | |
var pass bool | |
auth := new(proxy.Auth) | |
auth.User = u.User.Username() | |
auth.Password, pass = u.User.Password() | |
if pass { | |
dialer, _ := proxy.SOCKS5("tcp", u.Host, auth, proxy.Direct) | |
return dialer.Dial("tcp", hostport) | |
} | |
dialer, _ := proxy.SOCKS5("tcp", u.Host, nil, proxy.Direct) | |
return dialer.Dial("tcp", hostport) | |
case "http", "https": | |
username := u.User.Username() | |
password, _ := u.User.Password() | |
conn, err := net.Dial("tcp", u.Host) | |
if err != nil { | |
break | |
} | |
hdr := make(http.Header) | |
if u.User.String() != "" { | |
auth := username + ":" + password | |
hdr.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) | |
} | |
connectReq := &http.Request{ | |
Method: "CONNECT", | |
URL: &url.URL{Opaque: hostport}, | |
Host: hostport, | |
Header: hdr, | |
} | |
if err = connectReq.Write(conn); err != nil { | |
break | |
} | |
br := bufio.NewReader(conn) | |
response, err := http.ReadResponse(br, connectReq) | |
if err != nil || response == nil { | |
log.Printf("http proxy connection error %v", err) | |
break | |
} | |
if response.StatusCode != 200 { | |
fmt.Printf("connect http tunnel faild: %d %+v", response.StatusCode, response) | |
break | |
} | |
return conn, nil | |
} | |
return net.Dial("tcp", hostport) | |
} | |
func clientTLSConnWithProxy(proxy, hostport string) (*tls.Conn, error) { | |
config := tls.Config{InsecureSkipVerify: true} | |
var err error | |
var conn net.Conn | |
conn, err = dialProxy(proxy, hostport) | |
if err != nil { | |
log.Printf("error %v", err) | |
return nil, err | |
} | |
tlsConn := tls.Client(conn, &config) | |
err = tlsConn.Handshake() | |
if err != nil { | |
log.Printf("handshake failed %v", err) | |
return nil, err | |
} | |
return tlsConn, nil | |
} | |
func unhex(hexStr string) []byte { | |
hexStr = strings.ReplaceAll(hexStr, " ", "") | |
hexStr = strings.ReplaceAll(hexStr, "\r", "") | |
hexStr = strings.ReplaceAll(hexStr, "\n", "") | |
hexStr = strings.ReplaceAll(hexStr, "\t", "") | |
bytes, _ := hex.DecodeString(hexStr) | |
return bytes | |
} | |
func main() { | |
conn, err := clientTLSConnWithProxy("http://localhost:8888", "www.google.com:443") | |
if err == nil { | |
bin := unhex("474554202f20485454502f312e310d0a486f73743a2037342e3132352e3230302e3130310d0a557365722d4167656e743a206375726c2f372e36342e310d0a4163636570743a202a2f2a0d0a0d0a") | |
_, err := conn.Write(bin) | |
if err != nil { | |
log.Printf("send http request error") | |
} | |
buf := new(bytes.Buffer) | |
for { | |
conn.SetReadDeadline(time.Now().Add(5 * time.Second)) | |
p := make([]byte, 4096) | |
c, err := conn.Read(p) | |
if err != nil { | |
break | |
} | |
buf.Write(p[:c]) | |
} | |
log.Printf("response text %s", buf.Bytes()) | |
log.Printf("response hex %x", buf.Bytes()) | |
} else { | |
log.Fatalf("error tls connection failed %v", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment