Path: blob/main/mitm-socket/go/dialer_proxy_http.go
1029 views
package main12import (3"bufio"4"crypto/tls"5"encoding/base64"6"errors"7"fmt"8"io"9"io/ioutil"10"net"11"net/http"12"net/url"13"strings"14)1516func DialAddrViaHttpProxy(dialer net.Dialer, addr string, proxyUrl *url.URL, allowInsecure bool) (net.Conn, error) {17isSecure, proxyHost, err := getCleanHost(proxyUrl)1819fmt.Printf("Dialing proxy connect %s to %s\n", proxyHost, addr)20connectReq := &http.Request{21Method: "CONNECT",22URL: proxyUrl,23Host: addr,24Header: make(http.Header),25}2627if proxyUrl.User != nil {28proxyAuth := proxyUrl.User.String()29connectReq.Header.Set("Proxy-Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(proxyAuth))))30}3132conn, err := dialer.Dial("tcp", proxyHost)33if err != nil {34responseMessage := fmt.Sprintf("HTTP_PROXY_ERR dial failed (%s)", err)35return nil, errors.New(responseMessage)36}3738if isSecure {39proxyTlsConfig := &tls.Config{}40if allowInsecure {41proxyTlsConfig.InsecureSkipVerify = true42} else {43proxyTlsConfig.ServerName = proxyHost44}4546// NOTE: this is just the "wrapper" tls connection to the proxy. NOT to the destination47conn = tls.Client(conn, proxyTlsConfig)48}4950err = connectReq.Write(conn)51if err != nil {52responseMessage := fmt.Sprintf("HTTP_PROXY_ERR writing CONNECT request failed (%s)", err)53return nil, errors.New(responseMessage)54}55// Read response.56// Okay to use and discard buffered reader here, because57// TLS server will not speak until spoken to.58br := bufio.NewReader(conn)5960resp, err := http.ReadResponse(br, connectReq)61if err != nil {62conn.Close()63responseMessage := fmt.Sprintf("HTTP_PROXY_ERR reading CONNECT response failed (%s)", err)64return nil, errors.New(responseMessage)65}66defer resp.Body.Close()6768if resp.StatusCode != 200 {69body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 500))70if err != nil {71return nil, err72}73conn.Close()74responseMessage := fmt.Sprintf("HTTP_PROXY_ERR connection refused (%d)\n%s", resp.StatusCode, string(body))75return nil, errors.New(responseMessage)76}77return conn, nil78}7980func getCleanHost(proxyUrl *url.URL) (bool, string, error) {81var isSecure = false8283proxyHost := proxyUrl.Host8485if proxyUrl.Scheme == "" || proxyUrl.Scheme == "http" {86if strings.IndexRune(proxyHost, ':') == -1 {87proxyHost += ":80"88}89}9091if proxyUrl.Scheme == "https" || proxyUrl.Scheme == "wss" {92isSecure = true93if strings.IndexRune(proxyHost, ':') == -1 {94proxyHost += ":443"95}96}9798return isSecure, proxyHost, nil99}100101102