package ssh import ( "bufio" "crypto/tls" "encoding/base64" "fmt" "net" "strings" "time" "github.com/1Panel-dev/1Panel/core/global" ) type HTTPProxyDialer struct { Type string URL string User string Password string } func HTTPDial(dialer HTTPProxyDialer, network, addr string) (net.Conn, error) { var conn net.Conn var err error global.LOG.Debugf("Dialing HTTP proxy %s for %s", dialer.URL, addr) dialer.URL = strings.TrimPrefix(dialer.URL, dialer.Type+"://") if dialer.Type == "https" { conn, err = tls.DialWithDialer( &net.Dialer{Timeout: 30 * time.Second}, network, dialer.URL, &tls.Config{InsecureSkipVerify: true}, ) } else { conn, err = net.DialTimeout(network, dialer.URL, 30*time.Second) } if err != nil { return nil, err } conn.SetDeadline(time.Now().Add(30 * time.Second)) connectReq := fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", addr) connectReq += fmt.Sprintf("Host: %s\r\n", addr) connectReq += "User-Agent: Go-ssh-client/1.0\r\n" if dialer.User != "" { auth := base64.StdEncoding.EncodeToString( []byte(dialer.User + ":" + dialer.Password), ) connectReq += fmt.Sprintf("Proxy-Authorization: Basic %s\r\n", auth) } connectReq += "Connection: keep-alive\r\n\r\n" if _, err := conn.Write([]byte(connectReq)); err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) response, err := reader.ReadString('\n') if err != nil { conn.Close() return nil, err } if !strings.HasPrefix(response, "HTTP/1.1 200") && !strings.HasPrefix(response, "HTTP/1.0 200") { conn.Close() return nil, fmt.Errorf("proxy connection failed: %s", strings.TrimSpace(response)) } for { line, err := reader.ReadString('\n') if err != nil { conn.Close() return nil, err } if line == "\r\n" || line == "\n" { break } } conn.SetDeadline(time.Time{}) return conn, nil }