インターネット セキュリティがますます重視されるようになり、ユーザーのアクセス通信を保護するために HTTPS を使用する Web サイトが増えています。ただし、特定のシナリオでは、特定の要件を達成するためにプロキシを使用してトラフィックを転送する必要があります。この記事では、golang を使用して HTTPS トラフィックを転送できるプロキシ サーバーを作成する方法を紹介します。
1. HTTP プロキシの実装
まず、golang が HTTP プロキシを実装する方法を紹介します。
Golang の標準ライブラリは net/http/httputil パッケージを提供します。このパッケージには、ReverseProxy や DumpRequestOut などの HTTP プロキシの実装に必要なツールと関数がカプセル化されています。 ReverseProxy は、受信した要求を別の HTTP サーバーに転送できるリバース プロキシ サーバーを表します。 DumpRequestOut 関数は、リクエストが送信される前にリクエストの内容をバイナリ形式でエンコードして出力できるため、リダイレクトされた Web サイトのプロセスとインタラクションの詳細を理解するのに役立ちます。
次のコードを使用して、単純な HTTP プロキシを実装できます:
package main import ( "log" "net/http" "net/http/httputil" ) func main() { proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: "http", Host: "localhost:8080"}) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { proxy.ServeHTTP(w, r) }) log.Fatal(http.ListenAndServe(":10080", nil)) }
上記のコードでは、リバース プロキシ サーバーを作成し、受信したリクエストを http:// localhost:8080 に転送します。 、サーバーはポート 10080 で監視されます。 HTTP リクエストをプロキシ サーバーに送信すると、プロキシ サーバーはリクエストをローカル ポート 8080 に転送し、コンソールに出力します。
2. HTTPS プロキシの実装
次に、golang を使用して HTTPS プロキシを実装し、HTTPS トラフィックを転送できるようにする方法を紹介します。まず、安全な HTTPS 通信のために証明書を使用する必要があります。
1. 自己署名証明書の生成
openssl を使用して、テスト環境で HTTPS 通信用の自己署名証明書を生成できます。具体的な手順は次のとおりです。
ステップ 1: 秘密鍵 key.pem
openssl genrsa -out key.pem 2048
ステップ 2: 証明書要求証明書 csr.pem
openssl req -new -key key.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out crt.pem
package main import ( "log" "net" "net/http" "net/http/httputil" "time" ) func main() { // 代理的目标 target := "http://localhost:8080" // 对HTTPS请求使用自签名证书 certFile, keyFile := "crt.pem", "key.pem" cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { log.Fatal(err) } // 创建TLS配置 tlsConfig := &tls.Config{ Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS11, } // 创建反向代理 proxy := httputil.NewSingleHostReverseProxy(&url.URL{ Scheme: "http", Host: "localhost:8080", }) // 处理CONNECT请求 handleConnect := func(w http.ResponseWriter, r *http.Request) { // 解析主机地址 host, _, err := net.SplitHostPort(r.Host) if err != nil { http.Error(w, fmt.Sprintf("Invalid host: %s", err), http.StatusBadRequest) return } // 创建目标地址 targetHost := net.JoinHostPort(host, "443") // 设置超时时间为10s dialer := &net.Dialer{ Timeout: 10 * time.Second, } // 创建TLS连接 conn, err := tls.DialWithDialer(dialer, "tcp", targetHost, tlsConfig) if err != nil { http.Error(w, fmt.Sprintf("Unable to create TLS connection: %s", err), http.StatusServiceUnavailable) return } // 将握手成功的连接转发到目标服务器 hijacker, ok := w.(http.Hijacker) if !ok { http.Error(w, "Hijacking not supported", http.StatusInternalServerError) return } clientConn, _, err := hijacker.Hijack() if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return } // 向客户端发送连接成功的状态码 clientConn.Write([]byte("HTTP/1.1 200 Connection Established ")) // 进行双向数据拷贝 go func() { defer conn.Close() io.Copy(conn, clientConn) }() go func() { defer clientConn.Close() io.Copy(clientConn, conn) }() } // 设置HandlerFunc handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodConnect { handleConnect(w, r) return } proxy.ServeHTTP(w, r) }) // 监听 server := &http.Server{ Addr: ":10080", Handler: handlerFunc, TLSConfig: tlsConfig, TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0), } log.Fatal(server.ListenAndServeTLS("", "")) }
以上がgolang トラフィック https 転送の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。