mirror of https://github.com/fatedier/frp
frpc: support connectiong frps by socks5 proxy
parent
60ecd1d58c
commit
30af32728a
|
@ -185,7 +185,7 @@ func (ctl *Control) login() (err error) {
|
||||||
ctl.session.Close()
|
ctl.session.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
|
conn, err := frpNet.ConnectServerByProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
|
||||||
fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
|
fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -253,7 +253,7 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) {
|
||||||
}
|
}
|
||||||
conn = frpNet.WrapConn(stream)
|
conn = frpNet.WrapConn(stream)
|
||||||
} else {
|
} else {
|
||||||
conn, err = frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
|
conn, err = frpNet.ConnectServerByProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol,
|
||||||
fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
|
fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctl.Warn("start new connection to server error: %v", err)
|
ctl.Warn("start new connection to server error: %v", err)
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
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
|
# if you want to connect frps by http proxy or socks5 proxy, you can set http_proxy here or in global environment variables
|
||||||
# it only works when protocol is tcp
|
# it only works when protocol is tcp
|
||||||
# http_proxy = http://user:passwd@192.168.1.128:8080
|
# http_proxy = http://user:passwd@192.168.1.128:8080
|
||||||
|
# http_proxy = socks5://user:passwd@192.168.1.128:1080
|
||||||
|
|
||||||
# console or real logFile path like ./frpc.log
|
# console or real logFile path like ./frpc.log
|
||||||
log_file = ./frpc.log
|
log_file = ./frpc.log
|
||||||
|
|
|
@ -279,7 +279,7 @@ func TestPluginHttpProxy(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect method
|
// connect method
|
||||||
conn, err := net.ConnectTcpServerByHttpProxy("http://"+addr, fmt.Sprintf("127.0.0.1:%d", TEST_TCP_FRP_PORT))
|
conn, err := net.ConnectTcpServerByProxy("http://"+addr, fmt.Sprintf("127.0.0.1:%d", TEST_TCP_FRP_PORT))
|
||||||
if assert.NoError(err) {
|
if assert.NoError(err) {
|
||||||
res, err := sendTcpMsgByConn(conn, TEST_TCP_ECHO_STR)
|
res, err := sendTcpMsgByConn(conn, TEST_TCP_ECHO_STR)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
|
@ -122,10 +122,10 @@ func ConnectServer(protocol string, addr string) (c Conn, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectServerByHttpProxy(httpProxy string, protocol string, addr string) (c Conn, err error) {
|
func ConnectServerByProxy(proxyUrl string, protocol string, addr string) (c Conn, err error) {
|
||||||
switch protocol {
|
switch protocol {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
return ConnectTcpServerByHttpProxy(httpProxy, addr)
|
return ConnectTcpServerByProxy(proxyUrl, addr)
|
||||||
case "kcp":
|
case "kcp":
|
||||||
// http proxy is not supported for kcp
|
// http proxy is not supported for kcp
|
||||||
return ConnectServer(protocol, addr)
|
return ConnectServer(protocol, addr)
|
||||||
|
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/fatedier/frp/utils/log"
|
"github.com/fatedier/frp/utils/log"
|
||||||
|
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TcpListener struct {
|
type TcpListener struct {
|
||||||
|
@ -93,7 +95,7 @@ type TcpConn struct {
|
||||||
log.Logger
|
log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpConn(conn *net.TCPConn) (c *TcpConn) {
|
func NewTcpConn(conn net.Conn) (c *TcpConn) {
|
||||||
c = &TcpConn{
|
c = &TcpConn{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
Logger: log.NewPrefixLogger(""),
|
Logger: log.NewPrefixLogger(""),
|
||||||
|
@ -114,28 +116,41 @@ func ConnectTcpServer(addr string) (c Conn, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectTcpServerByHttpProxy try to connect remote server by http proxy.
|
// ConnectTcpServerByProxy try to connect remote server by proxy.
|
||||||
// If httpProxy is empty, it will connect server directly.
|
func ConnectTcpServerByProxy(proxyStr string, serverAddr string) (c Conn, err error) {
|
||||||
func ConnectTcpServerByHttpProxy(httpProxy string, serverAddr string) (c Conn, err error) {
|
if proxyStr == "" {
|
||||||
if httpProxy == "" {
|
|
||||||
return ConnectTcpServer(serverAddr)
|
return ConnectTcpServer(serverAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxyUrl *url.URL
|
var (
|
||||||
if proxyUrl, err = url.Parse(httpProxy); err != nil {
|
proxyUrl *url.URL
|
||||||
|
username string
|
||||||
|
passwd string
|
||||||
|
)
|
||||||
|
if proxyUrl, err = url.Parse(proxyStr); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if proxyUrl.User != nil {
|
||||||
|
username = proxyUrl.User.Username()
|
||||||
|
passwd, _ = proxyUrl.User.Password()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch proxyUrl.Scheme {
|
||||||
|
case "http":
|
||||||
|
return ConnectTcpServerByHttpProxy(proxyUrl, username, passwd, serverAddr)
|
||||||
|
case "socks5":
|
||||||
|
return ConnectTcpServerBySocks5Proxy(proxyUrl, username, passwd, serverAddr)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Proxy URL scheme must be http or socks5, not [%s]", proxyUrl.Scheme)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectTcpServerByHttpProxy try to connect remote server by http proxy.
|
||||||
|
func ConnectTcpServerByHttpProxy(proxyUrl *url.URL, user string, passwd string, serverAddr string) (c Conn, err error) {
|
||||||
var proxyAuth string
|
var proxyAuth string
|
||||||
if proxyUrl.User != nil {
|
if proxyUrl.User != nil {
|
||||||
username := proxyUrl.User.Username()
|
proxyAuth = "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+passwd))
|
||||||
passwd, _ := proxyUrl.User.Password()
|
|
||||||
proxyAuth = "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+passwd))
|
|
||||||
}
|
|
||||||
|
|
||||||
if proxyUrl.Scheme != "http" {
|
|
||||||
err = fmt.Errorf("Proxy URL scheme must be http, not [%s]", proxyUrl.Scheme)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c, err = ConnectTcpServer(proxyUrl.Host); err != nil {
|
if c, err = ConnectTcpServer(proxyUrl.Host); err != nil {
|
||||||
|
@ -161,6 +176,27 @@ func ConnectTcpServerByHttpProxy(httpProxy string, serverAddr string) (c Conn, e
|
||||||
err = fmt.Errorf("ConnectTcpServer using proxy error, StatusCode [%d]", resp.StatusCode)
|
err = fmt.Errorf("ConnectTcpServer using proxy error, StatusCode [%d]", resp.StatusCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConnectTcpServerBySocks5Proxy(proxyUrl *url.URL, user string, passwd string, serverAddr string) (c Conn, err error) {
|
||||||
|
var auth *proxy.Auth
|
||||||
|
if proxyUrl.User != nil {
|
||||||
|
auth = &proxy.Auth{
|
||||||
|
User: user,
|
||||||
|
Password: passwd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer, err := proxy.SOCKS5("tcp", proxyUrl.Host, auth, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var conn net.Conn
|
||||||
|
if conn, err = dialer.Dial("tcp", serverAddr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c = NewTcpConn(conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue