frp/models/plugin/socks5.go
doggeddog 5b6f18084c add multiple network interface support for socks5 plugin
Similar with wget(--bind-address) or cURL(--interface),
you can bind with a specific network interface.
The parameter can be a host name.

plugin_bind_addr = 172.21.0.107
2018-11-16 19:48:29 +08:00

93 lines
2.2 KiB
Go

// Copyright 2017 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plugin
import (
logger "github.com/fatedier/frp/utils/log"
frpNet "github.com/fatedier/frp/utils/net"
"golang.org/x/net/context"
"io"
"io/ioutil"
"log"
"net"
gosocks5 "github.com/armon/go-socks5"
)
const PluginSocks5 = "socks5"
func init() {
Register(PluginSocks5, NewSocks5Plugin)
}
type Socks5Plugin struct {
Server *gosocks5.Server
user string
passwd string
}
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
user := params["plugin_user"]
passwd := params["plugin_passwd"]
bindAddr := params["plugin_bind_addr"]
cfg := &gosocks5.Config{
Logger: log.New(ioutil.Discard, "", log.LstdFlags),
}
if user != "" || passwd != "" {
cfg.Credentials = gosocks5.StaticCredentials(map[string]string{user: passwd})
}
if bindAddr != "" {
// bindAddr can be hostname
localAddr, err := net.ResolveIPAddr("ip", bindAddr)
if err != nil {
logger.Warn("Failed to resolve socks5 bind address: %v", bindAddr)
} else {
logger.Info("Bind address resolve to: %v", localAddr.IP)
localTCPAddr := net.TCPAddr{
IP: localAddr.IP,
}
cfg.Dial = func(ctx context.Context, net_, addr string) (net.Conn, error) {
d := net.Dialer{
LocalAddr: &localTCPAddr,
}
return d.Dial(net_, addr)
}
}
}
sp := &Socks5Plugin{}
sp.Server, err = gosocks5.New(cfg)
p = sp
return
}
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn frpNet.Conn) {
defer conn.Close()
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
sp.Server.ServeConn(wrapConn)
}
func (sp *Socks5Plugin) Name() string {
return PluginSocks5
}
func (sp *Socks5Plugin) Close() error {
return nil
}