Rumah >pembangunan bahagian belakang >Golang >pemajuan https lalu lintas golang

pemajuan https lalu lintas golang

王林
王林asal
2023-05-10 09:17:06945semak imbas

Dengan penekanan yang semakin meningkat pada keselamatan Internet, semakin banyak tapak web mula menggunakan HTTPS untuk melindungi komunikasi akses pengguna. Walau bagaimanapun, dalam beberapa senario tertentu, kita perlu menggunakan proksi untuk memajukan trafik untuk mencapai keperluan khusus tertentu. Artikel ini akan memperkenalkan cara menggunakan golang untuk menulis pelayan proksi yang boleh memajukan trafik HTTPS.

1. Pelaksanaan proksi HTTP

Pertama, mari perkenalkan cara golang melaksanakan proksi HTTP.

Pustaka standard Golang menyediakan pakej net/http/httputil, yang merangkumi alatan dan fungsi yang diperlukan untuk melaksanakan proksi HTTP, seperti ReverseProxy dan DumpRequestOut. ReverseProxy mewakili pelayan proksi terbalik yang boleh memajukan permintaan yang diterima ke pelayan HTTP yang lain. Fungsi DumpRequestOut boleh mengekod dan mengeluarkan kandungan permintaan dalam format binari sebelum permintaan dihantar. Ini akan membantu kami memahami proses dan butiran interaksi tapak web yang diubah hala.

Kami boleh menggunakan kod berikut untuk melaksanakan proksi HTTP mudah:

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))
}

Dalam kod di atas, kami mencipta pelayan proksi terbalik dan memajukan permintaan yang diterima ke http:// localhost:8080 , dan pelayan dipantau pada port 10080. Apabila kami menghantar permintaan HTTP ke pelayan proksi, pelayan proksi akan memajukan permintaan ke port tempatan 8080 dan mengeluarkannya pada konsol.

2. Pelaksanaan proksi HTTPS

Seterusnya kami akan memperkenalkan cara menggunakan golang untuk melaksanakan proksi HTTPS supaya ia boleh memajukan trafik HTTPS. Pertama, kita perlu menggunakan sijil untuk komunikasi HTTPS yang selamat.

1. Penjanaan sijil yang ditandatangani sendiri

Kami boleh menggunakan openssl untuk menjana sijil yang ditandatangani sendiri untuk komunikasi HTTPS dalam persekitaran ujian. Langkah-langkah khusus adalah seperti berikut:

Langkah 1: Jana kunci peribadi.pem

openssl genrsa -out key.pem 2048

Langkah 2: Jana sijil permintaan sijil csr.pem

openssl req -new -key key.pem -out csr.pem

Selepas melepasi perkara di atas dua langkah, Kami telah mencipta kunci peribadi dan fail permintaan sijil untuk mencipta sijil yang ditandatangani sendiri.

Langkah 3: Jana sijil crt.pem

Kita boleh menggunakan csr.pem dan key.pem untuk menjana sijil yang ditandatangani sendiri:

openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out crt.pem

Dalam langkah ini, kami Had masa 365 hari telah digunakan dan sijil crt.pem telah dijana.

Pada ketika ini, kami telah mencipta sijil yang ditandatangani sendiri dan boleh menggunakannya untuk komunikasi HTTPS.

2. Laksanakan proksi HTTPS

Mula-mula kita perlu menghuraikan permintaan pelanggan dan membaca Pengepala yang sepadan untuk mendapatkan alamat hos yang diminta oleh pelanggan. Kami kemudiannya boleh membuat sambungan TLS untuk pelanggan dan memajukannya ke pelayan sasaran selepas jabat tangan yang berjaya. Perlu diingatkan bahawa dalam sistem Windows dan macOS, versi minimum TLS perlu dinyatakan sebagai 1.1, jika tidak sambungan akan ditutup secara paksa.

Berikut ialah contoh kod proksi HTTPS:

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("", ""))
}

Kod di atas melaksanakan pelayan proksi HTTPS asas dan boleh memajukan permintaan HTTPS yang diterima ke pelayan sasaran. Perlu diingatkan bahawa semasa penggunaan sebenar, kita perlu membuat pelarasan yang sepadan mengikut keperluan sebenar, seperti menggunakan sijil yang dikeluarkan oleh CA untuk mengukuhkan keselamatan HTTPS.

3. Ringkasan

Dalam artikel ini, kami memperkenalkan cara menggunakan golang untuk melaksanakan pelayan proksi dan melengkapkan pemajuan trafik protokol HTTP dan HTTPS. Untuk keperluan untuk memajukan trafik rangkaian, melaksanakan pelayan proksi boleh membantu kami mencapai matlamat kami dengan baik, dan ia juga meningkatkan pemahaman dan penggunaan protokol komunikasi rangkaian kami.

Atas ialah kandungan terperinci pemajuan https lalu lintas golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn