mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
frpc: add support for connecting server through http proxies, see #67
This commit is contained in:
parent
47c1a3e52c
commit
e262ac6abd
@ -4,6 +4,8 @@
|
|||||||
# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
|
# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
|
||||||
server_addr = 0.0.0.0
|
server_addr = 0.0.0.0
|
||||||
server_port = 7000
|
server_port = 7000
|
||||||
|
# if you want to connect frps by http proxy, you can set http_proxy here or in global environment variables
|
||||||
|
# http_proxy = http://user:pwd@192.168.1.128:8080
|
||||||
# console or real logFile path like ./frpc.log
|
# console or real logFile path like ./frpc.log
|
||||||
log_file = ./frpc.log
|
log_file = ./frpc.log
|
||||||
# debug, info, warn, error
|
# debug, info, warn, error
|
||||||
|
@ -130,7 +130,11 @@ func msgSender(cli *client.ProxyClient, c *conn.Conn, msgSendChan chan interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) {
|
func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) {
|
||||||
c, err = conn.ConnectServer(client.ServerAddr, client.ServerPort)
|
if client.HttpProxy == "" {
|
||||||
|
c, err = conn.ConnectServer(fmt.Sprintf("%s:%d", client.ServerAddr, client.ServerPort))
|
||||||
|
} else {
|
||||||
|
c, err = conn.ConnectServerByHttpProxy(client.HttpProxy, fmt.Sprintf("%s:%d", client.ServerAddr, client.ServerPort))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", cli.Name, client.ServerAddr, client.ServerPort, err)
|
log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", cli.Name, client.ServerAddr, client.ServerPort, err)
|
||||||
return
|
return
|
||||||
|
@ -37,7 +37,7 @@ type ProxyClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
|
func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
|
||||||
c, err = conn.ConnectServer(p.LocalIp, p.LocalPort)
|
c, err = conn.ConnectServer(fmt.Sprintf("%s:%d", p.LocalIp, p.LocalPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ProxyName [%s], connect to local port error, %v", p.Name, err)
|
log.Error("ProxyName [%s], connect to local port error, %v", p.Name, err)
|
||||||
}
|
}
|
||||||
@ -51,7 +51,11 @@ func (p *ProxyClient) GetRemoteConn(addr string, port int64) (c *conn.Conn, err
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c, err = conn.ConnectServer(addr, port)
|
if HttpProxy == "" {
|
||||||
|
c, err = conn.ConnectServer(fmt.Sprintf("%s:%d", addr, port))
|
||||||
|
} else {
|
||||||
|
c, err = conn.ConnectServerByHttpProxy(HttpProxy, fmt.Sprintf("%s:%d", addr, port))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", p.Name, addr, port, err)
|
log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", p.Name, addr, port, err)
|
||||||
return
|
return
|
||||||
|
@ -16,6 +16,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
ServerAddr string = "0.0.0.0"
|
ServerAddr string = "0.0.0.0"
|
||||||
ServerPort int64 = 7000
|
ServerPort int64 = 7000
|
||||||
|
HttpProxy string = ""
|
||||||
LogFile string = "console"
|
LogFile string = "console"
|
||||||
LogWay string = "console"
|
LogWay string = "console"
|
||||||
LogLevel string = "info"
|
LogLevel string = "info"
|
||||||
@ -57,6 +59,14 @@ func LoadConf(confFile string) (err error) {
|
|||||||
ServerPort, _ = strconv.ParseInt(tmpStr, 10, 64)
|
ServerPort, _ = strconv.ParseInt(tmpStr, 10, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmpStr, ok = conf.Get("common", "http_proxy")
|
||||||
|
if ok {
|
||||||
|
HttpProxy = tmpStr
|
||||||
|
} else {
|
||||||
|
// get http_proxy from env
|
||||||
|
HttpProxy = os.Getenv("http_proxy")
|
||||||
|
}
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "log_file")
|
tmpStr, ok = conf.Get("common", "log_file")
|
||||||
if ok {
|
if ok {
|
||||||
LogFile = tmpStr
|
LogFile = tmpStr
|
||||||
|
@ -16,9 +16,12 @@ package conn
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -104,9 +107,9 @@ func NewConn(conn net.Conn) (c *Conn) {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectServer(host string, port int64) (c *Conn, err error) {
|
func ConnectServer(addr string) (c *Conn, err error) {
|
||||||
c = &Conn{}
|
c = &Conn{}
|
||||||
servertAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", host, port))
|
servertAddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -120,6 +123,49 @@ func ConnectServer(host string, port int64) (c *Conn, err error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConnectServerByHttpProxy(httpProxy string, serverAddr string) (c *Conn, err error) {
|
||||||
|
var proxyUrl *url.URL
|
||||||
|
if proxyUrl, err = url.Parse(httpProxy); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var proxyAuth string
|
||||||
|
if proxyUrl.User != nil {
|
||||||
|
proxyAuth = "Basic " + base64.StdEncoding.EncodeToString([]byte(proxyUrl.User.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if proxyUrl.Scheme != "http" {
|
||||||
|
err = fmt.Errorf("Proxy URL scheme must be http, not [%s]", proxyUrl.Scheme)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c, err = ConnectServer(proxyUrl.Host); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("CONNECT", "https://"+serverAddr, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if proxyAuth != "" {
|
||||||
|
req.Header.Set("Proxy-Authorization", proxyAuth)
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", "Mozilla/5.0")
|
||||||
|
req.Write(c.TcpConn)
|
||||||
|
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(c), req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
err = fmt.Errorf("ConnectServer using proxy error, StatusCode [%d]", resp.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// if the tcpConn is different with c.TcpConn
|
// if the tcpConn is different with c.TcpConn
|
||||||
// you should call c.Close() first
|
// you should call c.Close() first
|
||||||
func (c *Conn) SetTcpConn(tcpConn net.Conn) {
|
func (c *Conn) SetTcpConn(tcpConn net.Conn) {
|
||||||
|
@ -19,7 +19,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEchoServer(t *testing.T) {
|
func TestEchoServer(t *testing.T) {
|
||||||
c, err := conn.ConnectServer("0.0.0.0", ECHO_PORT)
|
c, err := conn.ConnectServer(fmt.Sprintf("0.0.0.0:%d", ECHO_PORT))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("connect to echo server error: %v", err)
|
t.Fatalf("connect to echo server error: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user