1Panel/core/utils/ssh/http.go

81 lines
1.8 KiB
Go

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
}