|
@@ -9,6 +9,7 @@ import (
|
|
|
"github.com/fatedier/frp/models/proto/tcp"
|
|
|
"github.com/fatedier/frp/utils/log"
|
|
|
"github.com/fatedier/frp/utils/net"
|
|
|
+ "github.com/fatedier/frp/utils/vhost"
|
|
|
)
|
|
|
|
|
|
type Proxy interface {
|
|
@@ -42,6 +43,27 @@ func (pxy *BaseProxy) Close() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// startListenHandler start a goroutine handler for each listener.
|
|
|
+// p: p will just be passed to handler(Proxy, net.Conn).
|
|
|
+// handler: each proxy type can set different handler function to deal with connections accepted from listeners.
|
|
|
+func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn)) {
|
|
|
+ for _, listener := range pxy.listeners {
|
|
|
+ go func(l net.Listener) {
|
|
|
+ for {
|
|
|
+ // block
|
|
|
+ // if listener is closed, err returned
|
|
|
+ c, err := l.Accept()
|
|
|
+ if err != nil {
|
|
|
+ pxy.Info("listener is closed")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ pxy.Debug("get a user connection [%s]", c.RemoteAddr().String())
|
|
|
+ go handler(p, c)
|
|
|
+ }
|
|
|
+ }(listener)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy, err error) {
|
|
|
basePxy := BaseProxy{
|
|
|
name: pxyConf.GetName(),
|
|
@@ -83,25 +105,14 @@ type TcpProxy struct {
|
|
|
}
|
|
|
|
|
|
func (pxy *TcpProxy) Run() error {
|
|
|
- listener, err := net.ListenTcp(config.ServerCommonCfg.BindAddr, int64(pxy.cfg.RemotePort))
|
|
|
+ listener, err := net.ListenTcp(config.ServerCommonCfg.BindAddr, pxy.cfg.RemotePort)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
pxy.listeners = append(pxy.listeners, listener)
|
|
|
+ pxy.Info("tcp proxy listen port [%d]", pxy.cfg.RemotePort)
|
|
|
|
|
|
- go func(l net.Listener) {
|
|
|
- for {
|
|
|
- // block
|
|
|
- // if listener is closed, err returned
|
|
|
- c, err := l.Accept()
|
|
|
- if err != nil {
|
|
|
- pxy.Info("listener is closed")
|
|
|
- return
|
|
|
- }
|
|
|
- pxy.Debug("got one user connection [%s]", c.RemoteAddr().String())
|
|
|
- go HandleUserTcpConnection(pxy, c)
|
|
|
- }
|
|
|
- }(listener)
|
|
|
+ pxy.startListenHandler(pxy, HandleUserTcpConnection)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
@@ -119,6 +130,43 @@ type HttpProxy struct {
|
|
|
}
|
|
|
|
|
|
func (pxy *HttpProxy) Run() (err error) {
|
|
|
+ routeConfig := &vhost.VhostRouteConfig{
|
|
|
+ RewriteHost: pxy.cfg.HostHeaderRewrite,
|
|
|
+ Username: pxy.cfg.HttpUser,
|
|
|
+ Password: pxy.cfg.HttpPwd,
|
|
|
+ }
|
|
|
+
|
|
|
+ locations := pxy.cfg.Locations
|
|
|
+ if len(locations) == 0 {
|
|
|
+ locations = []string{""}
|
|
|
+ }
|
|
|
+ for _, domain := range pxy.cfg.CustomDomains {
|
|
|
+ routeConfig.Domain = domain
|
|
|
+ for _, location := range locations {
|
|
|
+ routeConfig.Location = location
|
|
|
+ l, err := pxy.ctl.svr.VhostHttpMuxer.Listen(routeConfig)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ pxy.Info("http proxy listen for host [%s] location [%s]", routeConfig.Domain, routeConfig.Location)
|
|
|
+ pxy.listeners = append(pxy.listeners, l)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if pxy.cfg.SubDomain != "" {
|
|
|
+ routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost
|
|
|
+ for _, location := range locations {
|
|
|
+ routeConfig.Location = location
|
|
|
+ l, err := pxy.ctl.svr.VhostHttpMuxer.Listen(routeConfig)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ pxy.Info("http proxy listen for host [%s] location [%s]", routeConfig.Domain, routeConfig.Location)
|
|
|
+ pxy.listeners = append(pxy.listeners, l)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pxy.startListenHandler(pxy, HandleUserTcpConnection)
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -136,6 +184,29 @@ type HttpsProxy struct {
|
|
|
}
|
|
|
|
|
|
func (pxy *HttpsProxy) Run() (err error) {
|
|
|
+ routeConfig := &vhost.VhostRouteConfig{}
|
|
|
+
|
|
|
+ for _, domain := range pxy.cfg.CustomDomains {
|
|
|
+ routeConfig.Domain = domain
|
|
|
+ l, err := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ pxy.Info("https proxy listen for host [%s]", routeConfig.Domain)
|
|
|
+ pxy.listeners = append(pxy.listeners, l)
|
|
|
+ }
|
|
|
+
|
|
|
+ if pxy.cfg.SubDomain != "" {
|
|
|
+ routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost
|
|
|
+ l, err := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ pxy.Info("https proxy listen for host [%s]", routeConfig.Domain)
|
|
|
+ pxy.listeners = append(pxy.listeners, l)
|
|
|
+ }
|
|
|
+
|
|
|
+ pxy.startListenHandler(pxy, HandleUserTcpConnection)
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -180,7 +251,7 @@ func HandleUserTcpConnection(pxy Proxy, userConn net.Conn) {
|
|
|
return
|
|
|
}
|
|
|
defer workConn.Close()
|
|
|
- pxy.Info("get one new work connection: %s", workConn.RemoteAddr().String())
|
|
|
+ pxy.Info("get a new work connection: [%s]", workConn.RemoteAddr().String())
|
|
|
workConn.AddLogPrefix(pxy.GetName())
|
|
|
|
|
|
err := msg.WriteMsg(workConn, &msg.StartWorkConn{
|
|
@@ -199,12 +270,7 @@ func HandleUserTcpConnection(pxy Proxy, userConn net.Conn) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- var (
|
|
|
- local io.ReadWriteCloser
|
|
|
- remote io.ReadWriteCloser
|
|
|
- )
|
|
|
- local = workConn
|
|
|
- remote = userConn
|
|
|
+ var local io.ReadWriteCloser = workConn
|
|
|
cfg := pxy.GetConf().GetBaseInfo()
|
|
|
if cfg.UseEncryption {
|
|
|
local, err = tcp.WithEncryption(local, []byte(config.ServerCommonCfg.PrivilegeToken))
|
|
@@ -216,5 +282,8 @@ func HandleUserTcpConnection(pxy Proxy, userConn net.Conn) {
|
|
|
if cfg.UseCompression {
|
|
|
local = tcp.WithCompression(local)
|
|
|
}
|
|
|
- tcp.Join(local, remote)
|
|
|
+ pxy.Debug("join connections, workConn(l[%s] r[%s]) userConn(l[%s] r[%s])", workConn.LocalAddr().String(),
|
|
|
+ workConn.RemoteAddr().String(), userConn.LocalAddr().String(), userConn.RemoteAddr().String())
|
|
|
+ tcp.Join(local, userConn)
|
|
|
+ pxy.Debug("join connections closed")
|
|
|
}
|