mirror of
https://github.com/ehang-io/nps.git
synced 2025-07-03 04:53:50 +00:00
Ip限制 npc代理连接
This commit is contained in:
parent
9f6b33a62b
commit
3b18d66835
@ -3,14 +3,15 @@ package bridge
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/kcp"
|
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -45,18 +46,21 @@ type Bridge struct {
|
|||||||
tunnelType string //bridge type kcp or tcp
|
tunnelType string //bridge type kcp or tcp
|
||||||
OpenTask chan *file.Tunnel
|
OpenTask chan *file.Tunnel
|
||||||
CloseClient chan int
|
CloseClient chan int
|
||||||
lock sync.Mutex
|
|
||||||
tunnelLock sync.Mutex
|
|
||||||
clientLock sync.RWMutex
|
clientLock sync.RWMutex
|
||||||
|
Register map[string]time.Time
|
||||||
|
registerLock sync.RWMutex
|
||||||
|
ipVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunnel(tunnelPort int, tunnelType string) *Bridge {
|
func NewTunnel(tunnelPort int, tunnelType string, ipVerify bool) *Bridge {
|
||||||
t := new(Bridge)
|
t := new(Bridge)
|
||||||
t.TunnelPort = tunnelPort
|
t.TunnelPort = tunnelPort
|
||||||
t.Client = make(map[int]*Client)
|
t.Client = make(map[int]*Client)
|
||||||
t.tunnelType = tunnelType
|
t.tunnelType = tunnelType
|
||||||
t.OpenTask = make(chan *file.Tunnel)
|
t.OpenTask = make(chan *file.Tunnel)
|
||||||
t.CloseClient = make(chan int)
|
t.CloseClient = make(chan int)
|
||||||
|
t.Register = make(map[string]time.Time)
|
||||||
|
t.ipVerify = ipVerify
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +132,6 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
|
|||||||
if flag, err := c.ReadFlag(); err == nil {
|
if flag, err := c.ReadFlag(); err == nil {
|
||||||
s.typeDeal(flag, c, id)
|
s.typeDeal(flag, c, id)
|
||||||
} else {
|
} else {
|
||||||
log.Println(222)
|
|
||||||
log.Println(err, flag)
|
log.Println(err, flag)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -180,13 +183,25 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
|||||||
go s.clientCopy(id)
|
go s.clientCopy(id)
|
||||||
case common.WORK_CONFIG:
|
case common.WORK_CONFIG:
|
||||||
go s.GetConfig(c)
|
go s.GetConfig(c)
|
||||||
|
case common.WORK_REGISTER:
|
||||||
|
go s.register(c)
|
||||||
}
|
}
|
||||||
c.SetAlive(s.tunnelType)
|
c.SetAlive(s.tunnelType)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Bridge) register(c *conn.Conn) {
|
||||||
|
var hour int32
|
||||||
|
if err := binary.Read(c, binary.LittleEndian, &hour); err == nil {
|
||||||
|
s.registerLock.Lock()
|
||||||
|
s.Register[common.GetIpByAddr(c.Conn.RemoteAddr().String())] = time.Now().Add(time.Hour * time.Duration(hour))
|
||||||
|
lg.Println(s.Register[common.GetIpByAddr(c.Conn.RemoteAddr().String())])
|
||||||
|
s.registerLock.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//等待
|
//等待
|
||||||
func (s *Bridge) waitStatus(clientId, id int) (bool) {
|
func (s *Bridge) waitStatus(clientId, id int) bool {
|
||||||
ticker := time.NewTicker(time.Millisecond * 100)
|
ticker := time.NewTicker(time.Millisecond * 100)
|
||||||
stop := time.After(time.Second * 10)
|
stop := time.After(time.Second * 10)
|
||||||
for {
|
for {
|
||||||
@ -209,13 +224,26 @@ func (s *Bridge) waitStatus(clientId, id int) (bool) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link) (tunnel *conn.Conn, err error) {
|
func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, linkAddr string) (tunnel *conn.Conn, err error) {
|
||||||
s.clientLock.Lock()
|
s.clientLock.Lock()
|
||||||
if v, ok := s.Client[clientId]; ok {
|
if v, ok := s.Client[clientId]; ok {
|
||||||
s.clientLock.Unlock()
|
s.clientLock.Unlock()
|
||||||
|
if s.ipVerify {
|
||||||
|
s.registerLock.Lock()
|
||||||
|
ip := common.GetIpByAddr(linkAddr)
|
||||||
|
if v, ok := s.Register[ip]; !ok {
|
||||||
|
s.registerLock.Unlock()
|
||||||
|
return nil, errors.New(fmt.Sprintf("The ip %s is not in the validation list", ip))
|
||||||
|
} else {
|
||||||
|
if !v.After(time.Now()) {
|
||||||
|
return nil, errors.New(fmt.Sprintf("The validity of the ip %s has expired", ip))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.registerLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
v.signal.SendLinkInfo(link)
|
v.signal.SendLinkInfo(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("send link information error:", err, link.Id)
|
lg.Println("send link information error:", err, link.Id)
|
||||||
@ -300,7 +328,7 @@ func (s *Bridge) GetConfig(c *conn.Conn) {
|
|||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
break
|
break
|
||||||
} else if file.GetCsvDb().IsHostExist(h.Host) {
|
} else if file.GetCsvDb().IsHostExist(h) {
|
||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
} else {
|
} else {
|
||||||
@ -383,7 +411,6 @@ func (s *Bridge) clientCopy(clientId int) {
|
|||||||
for {
|
for {
|
||||||
if id, err := client.tunnel.GetLen(); err != nil {
|
if id, err := client.tunnel.GetLen(); err != nil {
|
||||||
s.closeClient(clientId)
|
s.closeClient(clientId)
|
||||||
lg.Println("读取msg id 错误", err, id)
|
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
client.Lock()
|
client.Lock()
|
||||||
|
@ -5,11 +5,13 @@ import (
|
|||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/config"
|
"github.com/cnlh/nps/lib/config"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/kcp"
|
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
|
"github.com/cnlh/nps/vender/golang.org/x/net/proxy"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -21,12 +23,13 @@ type TRPClient struct {
|
|||||||
tunnel *conn.Conn
|
tunnel *conn.Conn
|
||||||
bridgeConnType string
|
bridgeConnType string
|
||||||
stop chan bool
|
stop chan bool
|
||||||
|
proxyUrl string
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
vKey string
|
vKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
//new client
|
//new client
|
||||||
func NewRPClient(svraddr string, vKey string, bridgeConnType string) *TRPClient {
|
func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl string) *TRPClient {
|
||||||
return &TRPClient{
|
return &TRPClient{
|
||||||
svrAddr: svraddr,
|
svrAddr: svraddr,
|
||||||
linkMap: make(map[int]*conn.Link),
|
linkMap: make(map[int]*conn.Link),
|
||||||
@ -34,13 +37,14 @@ func NewRPClient(svraddr string, vKey string, bridgeConnType string) *TRPClient
|
|||||||
vKey: vKey,
|
vKey: vKey,
|
||||||
bridgeConnType: bridgeConnType,
|
bridgeConnType: bridgeConnType,
|
||||||
stop: make(chan bool),
|
stop: make(chan bool),
|
||||||
|
proxyUrl: proxyUrl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//start
|
//start
|
||||||
func (s *TRPClient) Start() {
|
func (s *TRPClient) Start() {
|
||||||
retry:
|
retry:
|
||||||
c, err := NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_MAIN)
|
c, err := NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_MAIN, s.proxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("The connection server failed and will be reconnected in five seconds")
|
lg.Println("The connection server failed and will be reconnected in five seconds")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
@ -130,7 +134,7 @@ func (s *TRPClient) linkProcess(link *conn.Link, c *conn.Conn) {
|
|||||||
//隧道模式处理
|
//隧道模式处理
|
||||||
func (s *TRPClient) dealChan() {
|
func (s *TRPClient) dealChan() {
|
||||||
var err error
|
var err error
|
||||||
s.tunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_CHAN)
|
s.tunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_CHAN, s.proxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("connect to ", s.svrAddr, "error:", err)
|
lg.Println("connect to ", s.svrAddr, "error:", err)
|
||||||
return
|
return
|
||||||
@ -184,7 +188,7 @@ re:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
first = false
|
first = false
|
||||||
c, err := NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG)
|
c, err := NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG, cnf.CommonConfig.ProxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println(err)
|
lg.Println(err)
|
||||||
goto re
|
goto re
|
||||||
@ -220,24 +224,36 @@ re:
|
|||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
if !c.GetAddStatus() {
|
if !c.GetAddStatus() {
|
||||||
lg.Println(errAdd, v.Port)
|
lg.Println(errAdd, v.Ports)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Close()
|
c.Close()
|
||||||
|
|
||||||
NewRPClient(cnf.CommonConfig.Server, string(b), cnf.CommonConfig.Tp).Start()
|
NewRPClient(cnf.CommonConfig.Server, string(b), cnf.CommonConfig.Tp, cnf.CommonConfig.ProxyUrl).Start()
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a new connection with the server and verify it
|
//Create a new connection with the server and verify it
|
||||||
func NewConn(tp string, vkey string, server string, connType string) (*conn.Conn, error) {
|
func NewConn(tp string, vkey string, server string, connType string, proxyUrl string) (*conn.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
var connection net.Conn
|
var connection net.Conn
|
||||||
var sess *kcp.UDPSession
|
var sess *kcp.UDPSession
|
||||||
if tp == "tcp" {
|
if tp == "tcp" {
|
||||||
|
if proxyUrl != "" {
|
||||||
|
u, er := url.Parse(proxyUrl)
|
||||||
|
if er != nil {
|
||||||
|
return nil, er
|
||||||
|
}
|
||||||
|
n, er := proxy.FromURL(u, nil)
|
||||||
|
if er != nil {
|
||||||
|
return nil, er
|
||||||
|
}
|
||||||
|
connection, err = n.Dial("tcp", server)
|
||||||
|
} else {
|
||||||
connection, err = net.Dial("tcp", server)
|
connection, err = net.Dial("tcp", server)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sess, err = kcp.DialWithOptions(server, nil, 10, 3)
|
sess, err = kcp.DialWithOptions(server, nil, 10, 3)
|
||||||
conn.SetUdpSession(sess)
|
conn.SetUdpSession(sess)
|
||||||
|
20
client/register.go
Normal file
20
client/register.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterLocalIp(server string, vKey string, tp string, proxyUrl string, hour int) {
|
||||||
|
c, err := NewConn(tp, vKey, server, common.WORK_REGISTER, proxyUrl)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
if err := binary.Write(c, binary.LittleEndian, int32(hour)); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
log.Printf("Successful ip registration for local public network, the validity period is %d hours.", hour)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
52
client/status.go
Normal file
52
client/status.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"github.com/cnlh/nps/lib/config"
|
||||||
|
"github.com/cnlh/nps/lib/lg"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTaskStatus(path string) {
|
||||||
|
cnf, err := config.NewConfig(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
c, err := NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG, cnf.CommonConfig.ProxyUrl)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
if _, err := c.Write([]byte(common.WORK_STATUS)); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
if f, err := common.ReadAllFromFile(filepath.Join(common.GetTmpPath(), "npc_vkey.txt")); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
} else if _, err := c.Write([]byte(string(f))); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
if l, err := c.GetLen(); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
} else if b, err := c.ReadLen(l); err != nil {
|
||||||
|
lg.Fatalln(err)
|
||||||
|
} else {
|
||||||
|
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||||
|
for _, v := range cnf.Hosts {
|
||||||
|
if common.InArr(arr, v.Remark) {
|
||||||
|
log.Println(v.Remark, "ok")
|
||||||
|
} else {
|
||||||
|
log.Println(v.Remark, "not running")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range cnf.Tasks {
|
||||||
|
if common.InArr(arr, v.Remark) {
|
||||||
|
log.Println(v.Remark, "ok")
|
||||||
|
} else {
|
||||||
|
log.Println(v.Remark, "not running")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
@ -4,13 +4,11 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"github.com/cnlh/nps/client"
|
"github.com/cnlh/nps/client"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/config"
|
|
||||||
"github.com/cnlh/nps/lib/daemon"
|
"github.com/cnlh/nps/lib/daemon"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "v0.0.15"
|
const VERSION = "v0.0.15"
|
||||||
@ -21,6 +19,8 @@ var (
|
|||||||
verifyKey = flag.String("vkey", "", "Authentication key")
|
verifyKey = flag.String("vkey", "", "Authentication key")
|
||||||
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
||||||
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
||||||
|
proxyUrl = flag.String("proxy", "", "proxy socks5 url(eg:socks5://111:222@127.0.0.1:9007)")
|
||||||
|
registerTime = flag.Int("time", 2, "register time long /h")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -29,44 +29,10 @@ func main() {
|
|||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case "status":
|
case "status":
|
||||||
path := strings.Replace(os.Args[2], "-config=", "", -1)
|
path := strings.Replace(os.Args[2], "-config=", "", -1)
|
||||||
cnf, err := config.NewConfig(path)
|
client.GetTaskStatus(path)
|
||||||
if err != nil {
|
case "register":
|
||||||
log.Fatalln(err)
|
flag.CommandLine.Parse(os.Args[2:])
|
||||||
}
|
client.RegisterLocalIp(*serverAddr, *verifyKey, *connType, *proxyUrl, *registerTime)
|
||||||
c, err := client.NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
if _, err := c.Write([]byte(common.WORK_STATUS)); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
if f, err := common.ReadAllFromFile(filepath.Join(common.GetTmpPath(), "npc_vkey.txt")); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
} else if _, err := c.Write([]byte(string(f))); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
if l, err := c.GetLen(); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
} else if b, err := c.ReadLen(l); err != nil {
|
|
||||||
lg.Fatalln(err)
|
|
||||||
} else {
|
|
||||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
|
||||||
for _, v := range cnf.Hosts {
|
|
||||||
if common.InArr(arr, v.Remark) {
|
|
||||||
log.Println(v.Remark, "ok")
|
|
||||||
} else {
|
|
||||||
log.Println(v.Remark, "not running")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, v := range cnf.Tasks {
|
|
||||||
if common.InArr(arr, v.Remark) {
|
|
||||||
log.Println(v.Remark, "ok")
|
|
||||||
} else {
|
|
||||||
log.Println(v.Remark, "not running")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
daemon.InitDaemon("npc", common.GetRunPath(), common.GetTmpPath())
|
daemon.InitDaemon("npc", common.GetRunPath(), common.GetTmpPath())
|
||||||
@ -76,7 +42,11 @@ func main() {
|
|||||||
lg.InitLogFile("npc", false, common.GetLogPath())
|
lg.InitLogFile("npc", false, common.GetLogPath())
|
||||||
}
|
}
|
||||||
if *verifyKey != "" && *serverAddr != "" {
|
if *verifyKey != "" && *serverAddr != "" {
|
||||||
client.NewRPClient(*serverAddr, *verifyKey, *connType).Start()
|
for {
|
||||||
|
client.NewRPClient(*serverAddr, *verifyKey, *connType, *proxyUrl).Start()
|
||||||
|
lg.Println("It will be reconnected in five seconds")
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
client.StartFromFile(*configPath)
|
client.StartFromFile(*configPath)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/daemon"
|
"github.com/cnlh/nps/lib/daemon"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
@ -10,6 +9,7 @@ import (
|
|||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"github.com/cnlh/nps/server"
|
"github.com/cnlh/nps/server"
|
||||||
"github.com/cnlh/nps/server/test"
|
"github.com/cnlh/nps/server/test"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
_ "github.com/cnlh/nps/web/routers"
|
_ "github.com/cnlh/nps/web/routers"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -38,3 +38,6 @@ publicVkey=123
|
|||||||
|
|
||||||
#Open ports allowed on the server side
|
#Open ports allowed on the server side
|
||||||
allowPorts=9001-9100,10001,11000-12000
|
allowPorts=9001-9100,10001,11000-12000
|
||||||
|
|
||||||
|
|
||||||
|
ipLimit=true
|
@ -1 +1,3 @@
|
|||||||
a.o.com,127.0.0.1:8080,7,,,,,1
|
a.o.com,127.0.0.1:8080,7,,,,/,1
|
||||||
|
a.o.com,127.0.0.1:7002,7,,,,/test,3
|
||||||
|
b.o.com,127.0.0.1:8082,7,,,,,4
|
||||||
|
|
@ -1,15 +1,18 @@
|
|||||||
[common]
|
[common]
|
||||||
server=127.0.0.1:8284
|
server=123.206.77.88:8284
|
||||||
tp=tcp
|
tp=tcp
|
||||||
vkey=123
|
vkey=123
|
||||||
compress=snappy
|
compress=snappy
|
||||||
crypt=true
|
crypt=true
|
||||||
auto_reconnection=true
|
auto_reconnection=true
|
||||||
|
username=111
|
||||||
|
password=222
|
||||||
|
proxy_socks5_url=socks5://111:222@118.89.159.126:8024
|
||||||
[web1]
|
[web1]
|
||||||
host=a.o.com
|
host=a.o.com
|
||||||
host_change=www.proxy.com
|
host_change=www.proxy.com
|
||||||
target=127.0.0.1:8080
|
target=127.0.0.1:8080
|
||||||
|
location=/test2
|
||||||
|
|
||||||
[web2]
|
[web2]
|
||||||
host=a.proxy.com
|
host=a.proxy.com
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
9010,socks5Server,,1,27,7,
|
|
@ -11,6 +11,7 @@ const (
|
|||||||
WORK_MAIN = "main"
|
WORK_MAIN = "main"
|
||||||
WORK_CHAN = "chan"
|
WORK_CHAN = "chan"
|
||||||
WORK_CONFIG = "conf"
|
WORK_CONFIG = "conf"
|
||||||
|
WORK_REGISTER = "rgst"
|
||||||
WORK_STATUS = "stus"
|
WORK_STATUS = "stus"
|
||||||
RES_SIGN = "sign"
|
RES_SIGN = "sign"
|
||||||
RES_MSG = "msg0"
|
RES_MSG = "msg0"
|
||||||
|
@ -59,7 +59,7 @@ func GetLogPath() string {
|
|||||||
func GetTmpPath() string {
|
func GetTmpPath() string {
|
||||||
var path string
|
var path string
|
||||||
if IsWindows() {
|
if IsWindows() {
|
||||||
path = "./"
|
path = GetRunPath()
|
||||||
} else {
|
} else {
|
||||||
path = "/tmp"
|
path = "/tmp"
|
||||||
}
|
}
|
||||||
|
@ -241,3 +241,8 @@ func FormatAddress(s string) string {
|
|||||||
}
|
}
|
||||||
return "127.0.0.1:" + s
|
return "127.0.0.1:" + s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetIpByAddr(addr string) string {
|
||||||
|
arr := strings.Split(addr, ":")
|
||||||
|
return arr[0]
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ type CommonConfig struct {
|
|||||||
Tp string //bridgeType kcp or tcp
|
Tp string //bridgeType kcp or tcp
|
||||||
AutoReconnection bool
|
AutoReconnection bool
|
||||||
Cnf *file.Config
|
Cnf *file.Config
|
||||||
|
ProxyUrl string
|
||||||
}
|
}
|
||||||
type Config struct {
|
type Config struct {
|
||||||
content string
|
content string
|
||||||
@ -94,6 +95,8 @@ func dealCommon(s string) *CommonConfig {
|
|||||||
c.Cnf.Compress = item[1]
|
c.Cnf.Compress = item[1]
|
||||||
case "crypt":
|
case "crypt":
|
||||||
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
||||||
|
case "proxy_socks5_url":
|
||||||
|
c.ProxyUrl = item[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
@ -115,6 +118,8 @@ func dealHost(s string) *file.Host {
|
|||||||
h.Target = strings.Replace(item[1], ",", "\n", -1)
|
h.Target = strings.Replace(item[1], ",", "\n", -1)
|
||||||
case "host_change":
|
case "host_change":
|
||||||
h.HostChange = item[1]
|
h.HostChange = item[1]
|
||||||
|
case "location":
|
||||||
|
h.Location = item[1]
|
||||||
default:
|
default:
|
||||||
if strings.Contains(item[0], "header") {
|
if strings.Contains(item[0], "header") {
|
||||||
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/kcp"
|
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
"github.com/cnlh/nps/lib/rate"
|
"github.com/cnlh/nps/lib/rate"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -276,7 +276,7 @@ func (s *Conn) SendHostInfo(h *file.Host) (int, error) {
|
|||||||
*/
|
*/
|
||||||
raw := bytes.NewBuffer([]byte{})
|
raw := bytes.NewBuffer([]byte{})
|
||||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_HOST))
|
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_HOST))
|
||||||
common.BinaryWrite(raw, h.Host, h.Target, h.HeaderChange, h.HostChange, h.Remark)
|
common.BinaryWrite(raw, h.Host, h.Target, h.HeaderChange, h.HostChange, h.Remark, h.Location)
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
return s.Write(raw.Bytes())
|
return s.Write(raw.Bytes())
|
||||||
@ -312,6 +312,7 @@ func (s *Conn) GetHostInfo() (h *file.Host, err error) {
|
|||||||
h.HeaderChange = arr[2]
|
h.HeaderChange = arr[2]
|
||||||
h.HostChange = arr[3]
|
h.HostChange = arr[3]
|
||||||
h.Remark = arr[4]
|
h.Remark = arr[4]
|
||||||
|
h.Location = arr[5]
|
||||||
h.Flow = new(file.Flow)
|
h.Flow = new(file.Flow)
|
||||||
h.NoStore = true
|
h.NoStore = true
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
"github.com/cnlh/nps/lib/rate"
|
"github.com/cnlh/nps/lib/rate"
|
||||||
"github.com/cnlh/nps/lib/snappy"
|
"github.com/cnlh/nps/vender/github.com/golang/snappy"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
@ -49,7 +49,7 @@ func status(f string, pidPath string) bool {
|
|||||||
if !common.IsWindows() {
|
if !common.IsWindows() {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "ps -ax | awk '{ print $1 }' | grep "+string(b))
|
cmd = exec.Command("/bin/sh", "-c", "ps -ax | awk '{ print $1 }' | grep "+string(b))
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("tasklist", )
|
cmd = exec.Command("tasklist")
|
||||||
}
|
}
|
||||||
out, _ := cmd.Output()
|
out, _ := cmd.Output()
|
||||||
if strings.Index(string(out), string(b)) > -1 {
|
if strings.Index(string(out), string(b)) > -1 {
|
||||||
|
@ -9,6 +9,7 @@ var (
|
|||||||
CsvDb *Csv
|
CsvDb *Csv
|
||||||
once sync.Once
|
once sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
//init csv from file
|
//init csv from file
|
||||||
func GetCsvDb() *Csv {
|
func GetCsvDb() *Csv {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
|
@ -293,9 +293,9 @@ func (s *Csv) DelHost(id int) error {
|
|||||||
return errors.New("不存在")
|
return errors.New("不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) IsHostExist(host string) bool {
|
func (s *Csv) IsHostExist(h *Host) bool {
|
||||||
for _, v := range s.Hosts {
|
for _, v := range s.Hosts {
|
||||||
if v.Host == host {
|
if v.Host == h.Host && h.Location == v.Location {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,12 +459,6 @@ func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if h != nil {
|
if h != nil {
|
||||||
if h.Location != "/" {
|
|
||||||
r.RequestURI = strings.Replace(r.RequestURI, h.Location, "", 1)
|
|
||||||
}
|
|
||||||
if r.RequestURI == "" {
|
|
||||||
r.RequestURI = "/"
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = errors.New("The host could not be parsed")
|
err = errors.New("The host could not be parsed")
|
||||||
|
@ -4,11 +4,11 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/cnlh/nps/bridge"
|
"github.com/cnlh/nps/bridge"
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
@ -117,14 +117,14 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
|||||||
lastHost *file.Host
|
lastHost *file.Host
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
for {
|
|
||||||
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
||||||
lg.Printf("the url %s %s is not found !", r.Host, r.RequestURI)
|
lg.Printf("the url %s %s Can't be parsed!", r.Host, r.RequestURI)
|
||||||
break
|
goto end
|
||||||
} else if host != lastHost {
|
} else {
|
||||||
lastHost = host
|
lastHost = host
|
||||||
isConn = true
|
|
||||||
}
|
}
|
||||||
|
for {
|
||||||
|
start:
|
||||||
if isConn {
|
if isConn {
|
||||||
//流量限制
|
//流量限制
|
||||||
if host.Client.Flow.FlowLimit > 0 && (host.Client.Flow.FlowLimit<<20) < (host.Client.Flow.ExportFlow+host.Client.Flow.InletFlow) {
|
if host.Client.Flow.FlowLimit > 0 && (host.Client.Flow.FlowLimit<<20) < (host.Client.Flow.ExportFlow+host.Client.Flow.InletFlow) {
|
||||||
@ -136,7 +136,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
lk = conn.NewLink(host.Client.GetId(), common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.CompressEncode, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, c, host.Flow, nil, host.Client.Rate, nil)
|
lk = conn.NewLink(host.Client.GetId(), common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.CompressEncode, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, c, host.Flow, nil, host.Client.Rate, nil)
|
||||||
if tunnel, err = s.bridge.SendLinkInfo(host.Client.Id, lk); err != nil {
|
if tunnel, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String()); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -146,11 +146,18 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
||||||
|
lg.Printf("the url %s %s is not found !", r.Host, r.RequestURI)
|
||||||
|
break
|
||||||
|
} else if host != lastHost {
|
||||||
|
lastHost = host
|
||||||
|
isConn = true
|
||||||
|
goto start
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//根据设定,修改header和host
|
//根据设定,修改header和host
|
||||||
common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
||||||
b, err := httputil.DumpRequest(r, true)
|
b, err := httputil.DumpRequest(r, true)
|
||||||
lg.Println(string(b), r.RequestURI)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -160,7 +167,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
if isConn {
|
if isConn {
|
||||||
s.writeConnFail(c.Conn)
|
s.writeConnFail(c.Conn)
|
||||||
} else {
|
} else {
|
||||||
|
@ -143,7 +143,7 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) {
|
|||||||
}
|
}
|
||||||
link := conn.NewLink(s.task.Client.GetId(), ltype, addr, s.task.Client.Cnf.CompressEncode, s.task.Client.Cnf.CompressDecode, s.task.Client.Cnf.Crypt, conn.NewConn(c), s.task.Flow, nil, s.task.Client.Rate, nil)
|
link := conn.NewLink(s.task.Client.GetId(), ltype, addr, s.task.Client.Cnf.CompressEncode, s.task.Client.Cnf.CompressDecode, s.task.Client.Cnf.Crypt, conn.NewConn(c), s.task.Flow, nil, s.task.Client.Rate, nil)
|
||||||
|
|
||||||
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link); err != nil {
|
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, c.RemoteAddr().String()); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@ -244,7 +244,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
|
|||||||
if _, err := io.ReadAtLeast(c, pass, passLen); err != nil {
|
if _, err := io.ReadAtLeast(c, pass, passLen); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if string(pass) == s.task.Client.Cnf.U && string(user) == s.task.Client.Cnf.P {
|
if string(user) == s.task.Client.Cnf.U && string(pass) == s.task.Client.Cnf.P {
|
||||||
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
|
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -255,7 +255,6 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
|
|||||||
}
|
}
|
||||||
return errors.New("验证不通过")
|
return errors.New("验证不通过")
|
||||||
}
|
}
|
||||||
return errors.New("未知错误")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//start
|
//start
|
||||||
|
@ -3,11 +3,11 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/bridge"
|
"github.com/cnlh/nps/bridge"
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -53,7 +53,7 @@ func (s *TunnelModeServer) Start() error {
|
|||||||
func (s *TunnelModeServer) dealClient(c *conn.Conn, cnf *file.Config, addr string, method string, rb []byte) error {
|
func (s *TunnelModeServer) dealClient(c *conn.Conn, cnf *file.Config, addr string, method string, rb []byte) error {
|
||||||
link := conn.NewLink(s.task.Client.GetId(), common.CONN_TCP, addr, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, c, s.task.Flow, nil, s.task.Client.Rate, nil)
|
link := conn.NewLink(s.task.Client.GetId(), common.CONN_TCP, addr, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, c, s.task.Flow, nil, s.task.Client.Rate, nil)
|
||||||
|
|
||||||
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link); err != nil {
|
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, c.Conn.RemoteAddr().String()); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -105,8 +105,13 @@ func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
|||||||
method, addr, rb, err, r := c.GetHost()
|
method, addr, rb, err, r := c.GetHost()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
|
lg.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if r.Method == "CONNECT" {
|
||||||
|
c.Write([]byte("HTTP/1.1 200 Connection Established\r\n"))
|
||||||
|
rb = nil //reset
|
||||||
|
}
|
||||||
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P); err != nil {
|
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
|||||||
if err := s.checkFlow(); err != nil {
|
if err := s.checkFlow(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link); err != nil {
|
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, addr.String()); err != nil {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
s.task.Flow.Add(len(data), 0)
|
s.task.Flow.Add(len(data), 0)
|
||||||
|
@ -3,11 +3,12 @@ package server
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/bridge"
|
"github.com/cnlh/nps/bridge"
|
||||||
"github.com/cnlh/nps/lib/beego"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/lg"
|
||||||
"github.com/cnlh/nps/server/proxy"
|
"github.com/cnlh/nps/server/proxy"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,13 +24,15 @@ func init() {
|
|||||||
//从csv文件中恢复任务
|
//从csv文件中恢复任务
|
||||||
func InitFromCsv() {
|
func InitFromCsv() {
|
||||||
//Add a public password
|
//Add a public password
|
||||||
c := file.NewClient(beego.AppConfig.String("publicVkey"), true, true)
|
if vkey := beego.AppConfig.String("publicVkey"); vkey != "" {
|
||||||
|
c := file.NewClient(vkey, true, true)
|
||||||
file.GetCsvDb().NewClient(c)
|
file.GetCsvDb().NewClient(c)
|
||||||
RunList[c.Id] = nil
|
RunList[c.Id] = nil
|
||||||
|
}
|
||||||
//Initialize services in server-side files
|
//Initialize services in server-side files
|
||||||
for _, v := range file.GetCsvDb().Tasks {
|
for _, v := range file.GetCsvDb().Tasks {
|
||||||
if v.Status {
|
if v.Status {
|
||||||
lg.Println("启动模式:", v.Mode, "监听端口:", v.Port)
|
lg.Println("task start info: mode:", v.Mode, "port:", v.Port)
|
||||||
AddTask(v)
|
AddTask(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +51,7 @@ func DealBridgeTask() {
|
|||||||
|
|
||||||
//start a new server
|
//start a new server
|
||||||
func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
|
func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
|
||||||
Bridge = bridge.NewTunnel(bridgePort, bridgeType)
|
Bridge = bridge.NewTunnel(bridgePort, bridgeType, common.GetBoolByStr(beego.AppConfig.String("ipLimit")))
|
||||||
if err := Bridge.StartTunnel(); err != nil {
|
if err := Bridge.StartTunnel(); err != nil {
|
||||||
lg.Fatalln("服务端开启失败", err)
|
lg.Fatalln("服务端开启失败", err)
|
||||||
} else {
|
} else {
|
||||||
@ -241,7 +244,7 @@ func DelClientConnect(clientId int) {
|
|||||||
|
|
||||||
func GetDashboardData() map[string]int {
|
func GetDashboardData() map[string]int {
|
||||||
data := make(map[string]int)
|
data := make(map[string]int)
|
||||||
data["hostCount"] = len(file.GetCsvDb().Hosts)
|
data["hostCount"] = len(file.GetCsvDb().Hosts) - 1 //Remove the public key client
|
||||||
data["clientCount"] = len(file.GetCsvDb().Clients)
|
data["clientCount"] = len(file.GetCsvDb().Clients)
|
||||||
list := file.GetCsvDb().Clients
|
list := file.GetCsvDb().Clients
|
||||||
dealClientData(list)
|
dealClientData(list)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package tool
|
package tool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ports []int
|
var ports []int
|
||||||
|
168
vender/golang.org/x/net/internal/socks/client.go
Normal file
168
vender/golang.org/x/net/internal/socks/client.go
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
noDeadline = time.Time{}
|
||||||
|
aLongTimeAgo = time.Unix(1, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
|
||||||
|
host, port, err := splitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
|
||||||
|
c.SetDeadline(deadline)
|
||||||
|
defer c.SetDeadline(noDeadline)
|
||||||
|
}
|
||||||
|
if ctx != context.Background() {
|
||||||
|
errCh := make(chan error, 1)
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer func() {
|
||||||
|
close(done)
|
||||||
|
if ctxErr == nil {
|
||||||
|
ctxErr = <-errCh
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
c.SetDeadline(aLongTimeAgo)
|
||||||
|
errCh <- ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
errCh <- nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, 0, 6+len(host)) // the size here is just an estimate
|
||||||
|
b = append(b, Version5)
|
||||||
|
if len(d.AuthMethods) == 0 || d.Authenticate == nil {
|
||||||
|
b = append(b, 1, byte(AuthMethodNotRequired))
|
||||||
|
} else {
|
||||||
|
ams := d.AuthMethods
|
||||||
|
if len(ams) > 255 {
|
||||||
|
return nil, errors.New("too many authentication methods")
|
||||||
|
}
|
||||||
|
b = append(b, byte(len(ams)))
|
||||||
|
for _, am := range ams {
|
||||||
|
b = append(b, byte(am))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ctxErr = c.Write(b); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b[0] != Version5 {
|
||||||
|
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
|
||||||
|
}
|
||||||
|
am := AuthMethod(b[1])
|
||||||
|
if am == AuthMethodNoAcceptableMethods {
|
||||||
|
return nil, errors.New("no acceptable authentication methods")
|
||||||
|
}
|
||||||
|
if d.Authenticate != nil {
|
||||||
|
if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b = b[:0]
|
||||||
|
b = append(b, Version5, byte(d.cmd), 0)
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
|
b = append(b, AddrTypeIPv4)
|
||||||
|
b = append(b, ip4...)
|
||||||
|
} else if ip6 := ip.To16(); ip6 != nil {
|
||||||
|
b = append(b, AddrTypeIPv6)
|
||||||
|
b = append(b, ip6...)
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("unknown address type")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(host) > 255 {
|
||||||
|
return nil, errors.New("FQDN too long")
|
||||||
|
}
|
||||||
|
b = append(b, AddrTypeFQDN)
|
||||||
|
b = append(b, byte(len(host)))
|
||||||
|
b = append(b, host...)
|
||||||
|
}
|
||||||
|
b = append(b, byte(port>>8), byte(port))
|
||||||
|
if _, ctxErr = c.Write(b); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b[0] != Version5 {
|
||||||
|
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
|
||||||
|
}
|
||||||
|
if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded {
|
||||||
|
return nil, errors.New("unknown error " + cmdErr.String())
|
||||||
|
}
|
||||||
|
if b[2] != 0 {
|
||||||
|
return nil, errors.New("non-zero reserved field")
|
||||||
|
}
|
||||||
|
l := 2
|
||||||
|
var a Addr
|
||||||
|
switch b[3] {
|
||||||
|
case AddrTypeIPv4:
|
||||||
|
l += net.IPv4len
|
||||||
|
a.IP = make(net.IP, net.IPv4len)
|
||||||
|
case AddrTypeIPv6:
|
||||||
|
l += net.IPv6len
|
||||||
|
a.IP = make(net.IP, net.IPv6len)
|
||||||
|
case AddrTypeFQDN:
|
||||||
|
if _, err := io.ReadFull(c, b[:1]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l += int(b[0])
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
|
||||||
|
}
|
||||||
|
if cap(b) < l {
|
||||||
|
b = make([]byte, l)
|
||||||
|
} else {
|
||||||
|
b = b[:l]
|
||||||
|
}
|
||||||
|
if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if a.IP != nil {
|
||||||
|
copy(a.IP, b)
|
||||||
|
} else {
|
||||||
|
a.Name = string(b[:len(b)-2])
|
||||||
|
}
|
||||||
|
a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
|
||||||
|
return &a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitHostPort(address string) (string, int, error) {
|
||||||
|
host, port, err := net.SplitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
portnum, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
if 1 > portnum || portnum > 0xffff {
|
||||||
|
return "", 0, errors.New("port number out of range " + port)
|
||||||
|
}
|
||||||
|
return host, portnum, nil
|
||||||
|
}
|
170
vender/golang.org/x/net/internal/socks/dial_test.go
Normal file
170
vender/golang.org/x/net/internal/socks/dial_test.go
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package socks_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/socks"
|
||||||
|
"golang.org/x/net/internal/sockstest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDial(t *testing.T) {
|
||||||
|
t.Run("Connect", func(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
d.AuthMethods = []socks.AuthMethod{
|
||||||
|
socks.AuthMethodNotRequired,
|
||||||
|
socks.AuthMethodUsernamePassword,
|
||||||
|
}
|
||||||
|
d.Authenticate = (&socks.UsernamePassword{
|
||||||
|
Username: "username",
|
||||||
|
Password: "password",
|
||||||
|
}).Authenticate
|
||||||
|
c, err := d.DialContext(context.Background(), ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c.(*socks.Conn).BoundAddr()
|
||||||
|
c.Close()
|
||||||
|
})
|
||||||
|
t.Run("ConnectWithConn", func(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
c, err := net.Dial(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
d.AuthMethods = []socks.AuthMethod{
|
||||||
|
socks.AuthMethodNotRequired,
|
||||||
|
socks.AuthMethodUsernamePassword,
|
||||||
|
}
|
||||||
|
d.Authenticate = (&socks.UsernamePassword{
|
||||||
|
Username: "username",
|
||||||
|
Password: "password",
|
||||||
|
}).Authenticate
|
||||||
|
a, err := d.DialWithConn(context.Background(), c, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := a.(*socks.Addr); !ok {
|
||||||
|
t.Fatalf("got %+v; want socks.Addr", a)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.Run("Cancel", func(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
dialErr := make(chan error)
|
||||||
|
go func() {
|
||||||
|
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||||
|
if err == nil {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
dialErr <- err
|
||||||
|
}()
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
cancel()
|
||||||
|
err = <-dialErr
|
||||||
|
if perr, nerr := parseDialError(err); perr != context.Canceled && nerr == nil {
|
||||||
|
t.Fatalf("got %v; want context.Canceled or equivalent", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.Run("Deadline", func(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, blackholeCmdFunc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
|
||||||
|
defer cancel()
|
||||||
|
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||||
|
if err == nil {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
if perr, nerr := parseDialError(err); perr != context.DeadlineExceeded && nerr == nil {
|
||||||
|
t.Fatalf("got %v; want context.DeadlineExceeded or equivalent", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.Run("WithRogueServer", func(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, rogueCmdFunc)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
d := socks.NewDialer(ss.Addr().Network(), ss.Addr().String())
|
||||||
|
for i := 0; i < 2*len(rogueCmdList); i++ {
|
||||||
|
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Millisecond))
|
||||||
|
defer cancel()
|
||||||
|
c, err := d.DialContext(ctx, ss.TargetAddr().Network(), ss.TargetAddr().String())
|
||||||
|
if err == nil {
|
||||||
|
t.Log(c.(*socks.Conn).BoundAddr())
|
||||||
|
c.Close()
|
||||||
|
t.Error("should fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func blackholeCmdFunc(rw io.ReadWriter, b []byte) error {
|
||||||
|
if _, err := sockstest.ParseCmdRequest(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var bb [1]byte
|
||||||
|
for {
|
||||||
|
if _, err := rw.Read(bb[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rogueCmdFunc(rw io.ReadWriter, b []byte) error {
|
||||||
|
if _, err := sockstest.ParseCmdRequest(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rw.Write(rogueCmdList[rand.Intn(len(rogueCmdList))])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var rogueCmdList = [][]byte{
|
||||||
|
{0x05},
|
||||||
|
{0x06, 0x00, 0x00, 0x01, 192, 0, 2, 1, 0x17, 0x4b},
|
||||||
|
{0x05, 0x00, 0xff, 0x01, 192, 0, 2, 2, 0x17, 0x4b},
|
||||||
|
{0x05, 0x00, 0x00, 0x01, 192, 0, 2, 3},
|
||||||
|
{0x05, 0x00, 0x00, 0x03, 0x04, 'F', 'Q', 'D', 'N'},
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDialError(err error) (perr, nerr error) {
|
||||||
|
if e, ok := err.(*net.OpError); ok {
|
||||||
|
err = e.Err
|
||||||
|
nerr = e
|
||||||
|
}
|
||||||
|
if e, ok := err.(*os.SyscallError); ok {
|
||||||
|
err = e.Err
|
||||||
|
}
|
||||||
|
perr = err
|
||||||
|
return
|
||||||
|
}
|
317
vender/golang.org/x/net/internal/socks/socks.go
Normal file
317
vender/golang.org/x/net/internal/socks/socks.go
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package socks provides a SOCKS version 5 client implementation.
|
||||||
|
//
|
||||||
|
// SOCKS protocol version 5 is defined in RFC 1928.
|
||||||
|
// Username/Password authentication for SOCKS version 5 is defined in
|
||||||
|
// RFC 1929.
|
||||||
|
package socks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Command represents a SOCKS command.
|
||||||
|
type Command int
|
||||||
|
|
||||||
|
func (cmd Command) String() string {
|
||||||
|
switch cmd {
|
||||||
|
case CmdConnect:
|
||||||
|
return "socks connect"
|
||||||
|
case cmdBind:
|
||||||
|
return "socks bind"
|
||||||
|
default:
|
||||||
|
return "socks " + strconv.Itoa(int(cmd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An AuthMethod represents a SOCKS authentication method.
|
||||||
|
type AuthMethod int
|
||||||
|
|
||||||
|
// A Reply represents a SOCKS command reply code.
|
||||||
|
type Reply int
|
||||||
|
|
||||||
|
func (code Reply) String() string {
|
||||||
|
switch code {
|
||||||
|
case StatusSucceeded:
|
||||||
|
return "succeeded"
|
||||||
|
case 0x01:
|
||||||
|
return "general SOCKS server failure"
|
||||||
|
case 0x02:
|
||||||
|
return "connection not allowed by ruleset"
|
||||||
|
case 0x03:
|
||||||
|
return "network unreachable"
|
||||||
|
case 0x04:
|
||||||
|
return "host unreachable"
|
||||||
|
case 0x05:
|
||||||
|
return "connection refused"
|
||||||
|
case 0x06:
|
||||||
|
return "TTL expired"
|
||||||
|
case 0x07:
|
||||||
|
return "command not supported"
|
||||||
|
case 0x08:
|
||||||
|
return "address type not supported"
|
||||||
|
default:
|
||||||
|
return "unknown code: " + strconv.Itoa(int(code))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wire protocol constants.
|
||||||
|
const (
|
||||||
|
Version5 = 0x05
|
||||||
|
|
||||||
|
AddrTypeIPv4 = 0x01
|
||||||
|
AddrTypeFQDN = 0x03
|
||||||
|
AddrTypeIPv6 = 0x04
|
||||||
|
|
||||||
|
CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
|
||||||
|
cmdBind Command = 0x02 // establishes a passive-open forward proxy connection
|
||||||
|
|
||||||
|
AuthMethodNotRequired AuthMethod = 0x00 // no authentication required
|
||||||
|
AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password
|
||||||
|
AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods
|
||||||
|
|
||||||
|
StatusSucceeded Reply = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Addr represents a SOCKS-specific address.
|
||||||
|
// Either Name or IP is used exclusively.
|
||||||
|
type Addr struct {
|
||||||
|
Name string // fully-qualified domain name
|
||||||
|
IP net.IP
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Addr) Network() string { return "socks" }
|
||||||
|
|
||||||
|
func (a *Addr) String() string {
|
||||||
|
if a == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
port := strconv.Itoa(a.Port)
|
||||||
|
if a.IP == nil {
|
||||||
|
return net.JoinHostPort(a.Name, port)
|
||||||
|
}
|
||||||
|
return net.JoinHostPort(a.IP.String(), port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Conn represents a forward proxy connection.
|
||||||
|
type Conn struct {
|
||||||
|
net.Conn
|
||||||
|
|
||||||
|
boundAddr net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoundAddr returns the address assigned by the proxy server for
|
||||||
|
// connecting to the command target address from the proxy server.
|
||||||
|
func (c *Conn) BoundAddr() net.Addr {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.boundAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Dialer holds SOCKS-specific options.
|
||||||
|
type Dialer struct {
|
||||||
|
cmd Command // either CmdConnect or cmdBind
|
||||||
|
proxyNetwork string // network between a proxy server and a client
|
||||||
|
proxyAddress string // proxy server address
|
||||||
|
|
||||||
|
// ProxyDial specifies the optional dial function for
|
||||||
|
// establishing the transport connection.
|
||||||
|
ProxyDial func(context.Context, string, string) (net.Conn, error)
|
||||||
|
|
||||||
|
// AuthMethods specifies the list of request authention
|
||||||
|
// methods.
|
||||||
|
// If empty, SOCKS client requests only AuthMethodNotRequired.
|
||||||
|
AuthMethods []AuthMethod
|
||||||
|
|
||||||
|
// Authenticate specifies the optional authentication
|
||||||
|
// function. It must be non-nil when AuthMethods is not empty.
|
||||||
|
// It must return an error when the authentication is failed.
|
||||||
|
Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContext connects to the provided address on the provided
|
||||||
|
// network.
|
||||||
|
//
|
||||||
|
// The returned error value may be a net.OpError. When the Op field of
|
||||||
|
// net.OpError contains "socks", the Source field contains a proxy
|
||||||
|
// server address and the Addr field contains a command target
|
||||||
|
// address.
|
||||||
|
//
|
||||||
|
// See func Dial of the net package of standard library for a
|
||||||
|
// description of the network and address parameters.
|
||||||
|
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
if err := d.validateTarget(network, address); err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
if ctx == nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
var c net.Conn
|
||||||
|
if d.ProxyDial != nil {
|
||||||
|
c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
|
||||||
|
} else {
|
||||||
|
var dd net.Dialer
|
||||||
|
c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
a, err := d.connect(ctx, c, address)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
return &Conn{Conn: c, boundAddr: a}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialWithConn initiates a connection from SOCKS server to the target
|
||||||
|
// network and address using the connection c that is already
|
||||||
|
// connected to the SOCKS server.
|
||||||
|
//
|
||||||
|
// It returns the connection's local address assigned by the SOCKS
|
||||||
|
// server.
|
||||||
|
func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) {
|
||||||
|
if err := d.validateTarget(network, address); err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
if ctx == nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
|
||||||
|
}
|
||||||
|
a, err := d.connect(ctx, c, address)
|
||||||
|
if err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to the provided address on the provided network.
|
||||||
|
//
|
||||||
|
// Unlike DialContext, it returns a raw transport connection instead
|
||||||
|
// of a forward proxy connection.
|
||||||
|
//
|
||||||
|
// Deprecated: Use DialContext or DialWithConn instead.
|
||||||
|
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
|
||||||
|
if err := d.validateTarget(network, address); err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
var c net.Conn
|
||||||
|
if d.ProxyDial != nil {
|
||||||
|
c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress)
|
||||||
|
} else {
|
||||||
|
c, err = net.Dial(d.proxyNetwork, d.proxyAddress)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
proxy, dst, _ := d.pathAddrs(address)
|
||||||
|
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
|
||||||
|
}
|
||||||
|
if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dialer) validateTarget(network, address string) error {
|
||||||
|
switch network {
|
||||||
|
case "tcp", "tcp6", "tcp4":
|
||||||
|
default:
|
||||||
|
return errors.New("network not implemented")
|
||||||
|
}
|
||||||
|
switch d.cmd {
|
||||||
|
case CmdConnect, cmdBind:
|
||||||
|
default:
|
||||||
|
return errors.New("command not implemented")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
|
||||||
|
for i, s := range []string{d.proxyAddress, address} {
|
||||||
|
host, port, err := splitHostPort(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
a := &Addr{Port: port}
|
||||||
|
a.IP = net.ParseIP(host)
|
||||||
|
if a.IP == nil {
|
||||||
|
a.Name = host
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
proxy = a
|
||||||
|
} else {
|
||||||
|
dst = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDialer returns a new Dialer that dials through the provided
|
||||||
|
// proxy server's network and address.
|
||||||
|
func NewDialer(network, address string) *Dialer {
|
||||||
|
return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
authUsernamePasswordVersion = 0x01
|
||||||
|
authStatusSucceeded = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
|
// UsernamePassword are the credentials for the username/password
|
||||||
|
// authentication method.
|
||||||
|
type UsernamePassword struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate authenticates a pair of username and password with the
|
||||||
|
// proxy server.
|
||||||
|
func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error {
|
||||||
|
switch auth {
|
||||||
|
case AuthMethodNotRequired:
|
||||||
|
return nil
|
||||||
|
case AuthMethodUsernamePassword:
|
||||||
|
if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 {
|
||||||
|
return errors.New("invalid username/password")
|
||||||
|
}
|
||||||
|
b := []byte{authUsernamePasswordVersion}
|
||||||
|
b = append(b, byte(len(up.Username)))
|
||||||
|
b = append(b, up.Username...)
|
||||||
|
b = append(b, byte(len(up.Password)))
|
||||||
|
b = append(b, up.Password...)
|
||||||
|
// TODO(mikio): handle IO deadlines and cancelation if
|
||||||
|
// necessary
|
||||||
|
if _, err := rw.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(rw, b[:2]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b[0] != authUsernamePasswordVersion {
|
||||||
|
return errors.New("invalid username/password version")
|
||||||
|
}
|
||||||
|
if b[1] != authStatusSucceeded {
|
||||||
|
return errors.New("username/password authentication failed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
|
||||||
|
}
|
18
vender/golang.org/x/net/proxy/direct.go
Normal file
18
vender/golang.org/x/net/proxy/direct.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type direct struct{}
|
||||||
|
|
||||||
|
// Direct is a direct proxy: one that makes network connections directly.
|
||||||
|
var Direct = direct{}
|
||||||
|
|
||||||
|
func (direct) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
return net.Dial(network, addr)
|
||||||
|
}
|
140
vender/golang.org/x/net/proxy/per_host.go
Normal file
140
vender/golang.org/x/net/proxy/per_host.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A PerHost directs connections to a default Dialer unless the host name
|
||||||
|
// requested matches one of a number of exceptions.
|
||||||
|
type PerHost struct {
|
||||||
|
def, bypass Dialer
|
||||||
|
|
||||||
|
bypassNetworks []*net.IPNet
|
||||||
|
bypassIPs []net.IP
|
||||||
|
bypassZones []string
|
||||||
|
bypassHosts []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPerHost returns a PerHost Dialer that directs connections to either
|
||||||
|
// defaultDialer or bypass, depending on whether the connection matches one of
|
||||||
|
// the configured rules.
|
||||||
|
func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
|
||||||
|
return &PerHost{
|
||||||
|
def: defaultDialer,
|
||||||
|
bypass: bypass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to the address addr on the given network through either
|
||||||
|
// defaultDialer or bypass.
|
||||||
|
func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
|
||||||
|
host, _, err := net.SplitHostPort(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.dialerForRequest(host).Dial(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PerHost) dialerForRequest(host string) Dialer {
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
for _, net := range p.bypassNetworks {
|
||||||
|
if net.Contains(ip) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, bypassIP := range p.bypassIPs {
|
||||||
|
if bypassIP.Equal(ip) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.def
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, zone := range p.bypassZones {
|
||||||
|
if strings.HasSuffix(host, zone) {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
if host == zone[1:] {
|
||||||
|
// For a zone ".example.com", we match "example.com"
|
||||||
|
// too.
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, bypassHost := range p.bypassHosts {
|
||||||
|
if bypassHost == host {
|
||||||
|
return p.bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.def
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFromString parses a string that contains comma-separated values
|
||||||
|
// specifying hosts that should use the bypass proxy. Each value is either an
|
||||||
|
// IP address, a CIDR range, a zone (*.example.com) or a host name
|
||||||
|
// (localhost). A best effort is made to parse the string and errors are
|
||||||
|
// ignored.
|
||||||
|
func (p *PerHost) AddFromString(s string) {
|
||||||
|
hosts := strings.Split(s, ",")
|
||||||
|
for _, host := range hosts {
|
||||||
|
host = strings.TrimSpace(host)
|
||||||
|
if len(host) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(host, "/") {
|
||||||
|
// We assume that it's a CIDR address like 127.0.0.0/8
|
||||||
|
if _, net, err := net.ParseCIDR(host); err == nil {
|
||||||
|
p.AddNetwork(net)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
|
p.AddIP(ip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
p.AddZone(host[1:])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.AddHost(host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIP specifies an IP address that will use the bypass proxy. Note that
|
||||||
|
// this will only take effect if a literal IP address is dialed. A connection
|
||||||
|
// to a named host will never match an IP.
|
||||||
|
func (p *PerHost) AddIP(ip net.IP) {
|
||||||
|
p.bypassIPs = append(p.bypassIPs, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNetwork specifies an IP range that will use the bypass proxy. Note that
|
||||||
|
// this will only take effect if a literal IP address is dialed. A connection
|
||||||
|
// to a named host will never match.
|
||||||
|
func (p *PerHost) AddNetwork(net *net.IPNet) {
|
||||||
|
p.bypassNetworks = append(p.bypassNetworks, net)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
|
||||||
|
// "example.com" matches "example.com" and all of its subdomains.
|
||||||
|
func (p *PerHost) AddZone(zone string) {
|
||||||
|
if strings.HasSuffix(zone, ".") {
|
||||||
|
zone = zone[:len(zone)-1]
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(zone, ".") {
|
||||||
|
zone = "." + zone
|
||||||
|
}
|
||||||
|
p.bypassZones = append(p.bypassZones, zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHost specifies a host name that will use the bypass proxy.
|
||||||
|
func (p *PerHost) AddHost(host string) {
|
||||||
|
if strings.HasSuffix(host, ".") {
|
||||||
|
host = host[:len(host)-1]
|
||||||
|
}
|
||||||
|
p.bypassHosts = append(p.bypassHosts, host)
|
||||||
|
}
|
55
vender/golang.org/x/net/proxy/per_host_test.go
Normal file
55
vender/golang.org/x/net/proxy/per_host_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type recordingProxy struct {
|
||||||
|
addrs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *recordingProxy) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
r.addrs = append(r.addrs, addr)
|
||||||
|
return nil, errors.New("recordingProxy")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPerHost(t *testing.T) {
|
||||||
|
var def, bypass recordingProxy
|
||||||
|
perHost := NewPerHost(&def, &bypass)
|
||||||
|
perHost.AddFromString("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16")
|
||||||
|
|
||||||
|
expectedDef := []string{
|
||||||
|
"example.com:123",
|
||||||
|
"1.2.3.4:123",
|
||||||
|
"[1001::]:123",
|
||||||
|
}
|
||||||
|
expectedBypass := []string{
|
||||||
|
"localhost:123",
|
||||||
|
"zone:123",
|
||||||
|
"foo.zone:123",
|
||||||
|
"127.0.0.1:123",
|
||||||
|
"10.1.2.3:123",
|
||||||
|
"[1000::]:123",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range expectedDef {
|
||||||
|
perHost.Dial("tcp", addr)
|
||||||
|
}
|
||||||
|
for _, addr := range expectedBypass {
|
||||||
|
perHost.Dial("tcp", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expectedDef, def.addrs) {
|
||||||
|
t.Errorf("Hosts which went to the default proxy didn't match. Got %v, want %v", def.addrs, expectedDef)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(expectedBypass, bypass.addrs) {
|
||||||
|
t.Errorf("Hosts which went to the bypass proxy didn't match. Got %v, want %v", bypass.addrs, expectedBypass)
|
||||||
|
}
|
||||||
|
}
|
134
vender/golang.org/x/net/proxy/proxy.go
Normal file
134
vender/golang.org/x/net/proxy/proxy.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package proxy provides support for a variety of protocols to proxy network
|
||||||
|
// data.
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Dialer is a means to establish a connection.
|
||||||
|
type Dialer interface {
|
||||||
|
// Dial connects to the given address via the proxy.
|
||||||
|
Dial(network, addr string) (c net.Conn, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth contains authentication parameters that specific Dialers may require.
|
||||||
|
type Auth struct {
|
||||||
|
User, Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromEnvironment returns the dialer specified by the proxy related variables in
|
||||||
|
// the environment.
|
||||||
|
func FromEnvironment() Dialer {
|
||||||
|
allProxy := allProxyEnv.Get()
|
||||||
|
if len(allProxy) == 0 {
|
||||||
|
return Direct
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyURL, err := url.Parse(allProxy)
|
||||||
|
if err != nil {
|
||||||
|
return Direct
|
||||||
|
}
|
||||||
|
proxy, err := FromURL(proxyURL, Direct)
|
||||||
|
if err != nil {
|
||||||
|
return Direct
|
||||||
|
}
|
||||||
|
|
||||||
|
noProxy := noProxyEnv.Get()
|
||||||
|
if len(noProxy) == 0 {
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
perHost := NewPerHost(proxy, Direct)
|
||||||
|
perHost.AddFromString(noProxy)
|
||||||
|
return perHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxySchemes is a map from URL schemes to a function that creates a Dialer
|
||||||
|
// from a URL with such a scheme.
|
||||||
|
var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
|
||||||
|
|
||||||
|
// RegisterDialerType takes a URL scheme and a function to generate Dialers from
|
||||||
|
// a URL with that scheme and a forwarding Dialer. Registered schemes are used
|
||||||
|
// by FromURL.
|
||||||
|
func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
|
||||||
|
if proxySchemes == nil {
|
||||||
|
proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
|
||||||
|
}
|
||||||
|
proxySchemes[scheme] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromURL returns a Dialer given a URL specification and an underlying
|
||||||
|
// Dialer for it to make network requests.
|
||||||
|
func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
|
||||||
|
var auth *Auth
|
||||||
|
if u.User != nil {
|
||||||
|
auth = new(Auth)
|
||||||
|
auth.User = u.User.Username()
|
||||||
|
if p, ok := u.User.Password(); ok {
|
||||||
|
auth.Password = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "socks5":
|
||||||
|
return SOCKS5("tcp", u.Host, auth, forward)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the scheme doesn't match any of the built-in schemes, see if it
|
||||||
|
// was registered by another package.
|
||||||
|
if proxySchemes != nil {
|
||||||
|
if f, ok := proxySchemes[u.Scheme]; ok {
|
||||||
|
return f(u, forward)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
allProxyEnv = &envOnce{
|
||||||
|
names: []string{"ALL_PROXY", "all_proxy"},
|
||||||
|
}
|
||||||
|
noProxyEnv = &envOnce{
|
||||||
|
names: []string{"NO_PROXY", "no_proxy"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// envOnce looks up an environment variable (optionally by multiple
|
||||||
|
// names) once. It mitigates expensive lookups on some platforms
|
||||||
|
// (e.g. Windows).
|
||||||
|
// (Borrowed from net/http/transport.go)
|
||||||
|
type envOnce struct {
|
||||||
|
names []string
|
||||||
|
once sync.Once
|
||||||
|
val string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *envOnce) Get() string {
|
||||||
|
e.once.Do(e.init)
|
||||||
|
return e.val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *envOnce) init() {
|
||||||
|
for _, n := range e.names {
|
||||||
|
e.val = os.Getenv(n)
|
||||||
|
if e.val != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset is used by tests
|
||||||
|
func (e *envOnce) reset() {
|
||||||
|
e.once = sync.Once{}
|
||||||
|
e.val = ""
|
||||||
|
}
|
123
vender/golang.org/x/net/proxy/proxy_test.go
Normal file
123
vender/golang.org/x/net/proxy/proxy_test.go
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/internal/sockstest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type proxyFromEnvTest struct {
|
||||||
|
allProxyEnv string
|
||||||
|
noProxyEnv string
|
||||||
|
wantTypeOf Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t proxyFromEnvTest) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
space := func() {
|
||||||
|
if buf.Len() > 0 {
|
||||||
|
buf.WriteByte(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if t.allProxyEnv != "" {
|
||||||
|
fmt.Fprintf(&buf, "all_proxy=%q", t.allProxyEnv)
|
||||||
|
}
|
||||||
|
if t.noProxyEnv != "" {
|
||||||
|
space()
|
||||||
|
fmt.Fprintf(&buf, "no_proxy=%q", t.noProxyEnv)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromEnvironment(t *testing.T) {
|
||||||
|
ResetProxyEnv()
|
||||||
|
|
||||||
|
type dummyDialer struct {
|
||||||
|
direct
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterDialerType("irc", func(_ *url.URL, _ Dialer) (Dialer, error) {
|
||||||
|
return dummyDialer{}, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
proxyFromEnvTests := []proxyFromEnvTest{
|
||||||
|
{allProxyEnv: "127.0.0.1:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
|
||||||
|
{allProxyEnv: "ftp://example.com:8000", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
|
||||||
|
{allProxyEnv: "socks5://example.com:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: &PerHost{}},
|
||||||
|
{allProxyEnv: "irc://example.com:8000", wantTypeOf: dummyDialer{}},
|
||||||
|
{noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
|
||||||
|
{wantTypeOf: direct{}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range proxyFromEnvTests {
|
||||||
|
os.Setenv("ALL_PROXY", tt.allProxyEnv)
|
||||||
|
os.Setenv("NO_PROXY", tt.noProxyEnv)
|
||||||
|
ResetCachedEnvironment()
|
||||||
|
|
||||||
|
d := FromEnvironment()
|
||||||
|
if got, want := fmt.Sprintf("%T", d), fmt.Sprintf("%T", tt.wantTypeOf); got != want {
|
||||||
|
t.Errorf("%v: got type = %T, want %T", tt, d, tt.wantTypeOf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromURL(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
url, err := url.Parse("socks5://user:password@" + ss.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
proxy, err := FromURL(url, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c, err := proxy.Dial("tcp", "fqdn.doesnotexist:5963")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSOCKS5(t *testing.T) {
|
||||||
|
ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ss.Close()
|
||||||
|
proxy, err := SOCKS5("tcp", ss.Addr().String(), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c, err := proxy.Dial("tcp", ss.TargetAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResetProxyEnv() {
|
||||||
|
for _, env := range []*envOnce{allProxyEnv, noProxyEnv} {
|
||||||
|
for _, v := range env.names {
|
||||||
|
os.Setenv(v, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResetCachedEnvironment()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResetCachedEnvironment() {
|
||||||
|
allProxyEnv.reset()
|
||||||
|
noProxyEnv.reset()
|
||||||
|
}
|
36
vender/golang.org/x/net/proxy/socks5.go
Normal file
36
vender/golang.org/x/net/proxy/socks5.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/cnlh/nps/vender/golang.org/x/net/internal/socks"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given
|
||||||
|
// address with an optional username and password.
|
||||||
|
// See RFC 1928 and RFC 1929.
|
||||||
|
func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) {
|
||||||
|
d := socks.NewDialer(network, address)
|
||||||
|
if forward != nil {
|
||||||
|
d.ProxyDial = func(_ context.Context, network string, address string) (net.Conn, error) {
|
||||||
|
return forward.Dial(network, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if auth != nil {
|
||||||
|
up := socks.UsernamePassword{
|
||||||
|
Username: auth.User,
|
||||||
|
Password: auth.Password,
|
||||||
|
}
|
||||||
|
d.AuthMethods = []socks.AuthMethod{
|
||||||
|
socks.AuthMethodNotRequired,
|
||||||
|
socks.AuthMethodUsernamePassword,
|
||||||
|
}
|
||||||
|
d.Authenticate = up.Authenticate
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/beego"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/server"
|
"github.com/cnlh/nps/server"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -90,7 +90,7 @@ func (s *BaseController) AjaxErr(str string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//组装ajax
|
//组装ajax
|
||||||
func ajax(str string, status int) (map[string]interface{}) {
|
func ajax(str string, status int) map[string]interface{} {
|
||||||
json := make(map[string]interface{})
|
json := make(map[string]interface{})
|
||||||
json["status"] = status
|
json["status"] = status
|
||||||
json["msg"] = str
|
json["msg"] = str
|
||||||
|
@ -3,6 +3,7 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/server"
|
"github.com/cnlh/nps/server"
|
||||||
|
"github.com/cnlh/nps/server/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexController struct {
|
type IndexController struct {
|
||||||
@ -81,6 +82,9 @@ func (s *IndexController) Add() {
|
|||||||
Remark: s.GetString("remark"),
|
Remark: s.GetString("remark"),
|
||||||
Flow: &file.Flow{},
|
Flow: &file.Flow{},
|
||||||
}
|
}
|
||||||
|
if !tool.TestServerPort(t.Port, t.Mode) {
|
||||||
|
s.AjaxErr("The port cannot be opened because it may has been occupied or is no longer allowed.")
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
if t.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
if t.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||||
s.AjaxErr(err.Error())
|
s.AjaxErr(err.Error())
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginController struct {
|
type LoginController struct {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package routers
|
package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
"github.com/cnlh/nps/web/controllers"
|
"github.com/cnlh/nps/web/controllers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<th>客户端id</th>
|
<th>客户端id</th>
|
||||||
<th>备注</th>
|
<th>备注</th>
|
||||||
<th>host</th>
|
<th>host</th>
|
||||||
|
<th>location</th>
|
||||||
<th>内网目标</th>
|
<th>内网目标</th>
|
||||||
<th>host改写</th>
|
<th>host改写</th>
|
||||||
<th>压缩方式</th>
|
<th>压缩方式</th>
|
||||||
@ -77,6 +78,7 @@
|
|||||||
{data: 'Remark'},
|
{data: 'Remark'},
|
||||||
{data: 'Remark'},
|
{data: 'Remark'},
|
||||||
{data: 'Host'},
|
{data: 'Host'},
|
||||||
|
{data: 'Location'},
|
||||||
{data: 'Target'},
|
{data: 'Target'},
|
||||||
{data: 'HostChange'},
|
{data: 'HostChange'},
|
||||||
{data: 'HostChange'},
|
{data: 'HostChange'},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user