mirror of https://github.com/ehang-io/nps
P2p、install、log package
parent
45521d5680
commit
f6c596f318
|
@ -1,13 +1,17 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"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/crypt"
|
||||||
"github.com/cnlh/nps/lib/mux"
|
"github.com/cnlh/nps/lib/mux"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,6 +20,7 @@ type TRPClient struct {
|
||||||
bridgeConnType string
|
bridgeConnType string
|
||||||
proxyUrl string
|
proxyUrl string
|
||||||
vKey string
|
vKey string
|
||||||
|
p2pAddr map[string]string
|
||||||
tunnel *mux.Mux
|
tunnel *mux.Mux
|
||||||
signal *conn.Conn
|
signal *conn.Conn
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
|
@ -26,6 +31,7 @@ type TRPClient struct {
|
||||||
func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl string, cnf *config.Config) *TRPClient {
|
func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl string, cnf *config.Config) *TRPClient {
|
||||||
return &TRPClient{
|
return &TRPClient{
|
||||||
svrAddr: svraddr,
|
svrAddr: svraddr,
|
||||||
|
p2pAddr: make(map[string]string, 0),
|
||||||
vKey: vKey,
|
vKey: vKey,
|
||||||
bridgeConnType: bridgeConnType,
|
bridgeConnType: bridgeConnType,
|
||||||
proxyUrl: proxyUrl,
|
proxyUrl: proxyUrl,
|
||||||
|
@ -71,18 +77,30 @@ func (s *TRPClient) handleMain() {
|
||||||
logs.Warn(err)
|
logs.Warn(err)
|
||||||
return
|
return
|
||||||
} else if pwd, err := s.signal.GetShortLenContent(); err == nil {
|
} else if pwd, err := s.signal.GetShortLenContent(); err == nil {
|
||||||
go s.newUdpConn(string(lAddr), string(pwd))
|
var localAddr string
|
||||||
|
//The local port remains unchanged for a certain period of time
|
||||||
|
if v, ok := s.p2pAddr[crypt.Md5(string(pwd)+strconv.Itoa(int(time.Now().Unix()/100)))]; !ok {
|
||||||
|
tmpConn, err := common.GetLocalUdpAddr()
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localAddr = tmpConn.LocalAddr().String()
|
||||||
|
} else {
|
||||||
|
localAddr = v
|
||||||
|
}
|
||||||
|
go s.newUdpConn(localAddr, string(lAddr), string(pwd))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Close()
|
s.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TRPClient) newUdpConn(rAddr string, md5Password string) {
|
func (s *TRPClient) newUdpConn(localAddr, rAddr string, md5Password string) {
|
||||||
var localConn net.PacketConn
|
var localConn net.PacketConn
|
||||||
var err error
|
var err error
|
||||||
var remoteAddress string
|
var remoteAddress string
|
||||||
if remoteAddress, localConn, err = handleP2PUdp(rAddr, md5Password, common.WORK_P2P_PROVIDER); err != nil {
|
if remoteAddress, localConn, err = handleP2PUdp(localAddr, rAddr, md5Password, common.WORK_P2P_PROVIDER); err != nil {
|
||||||
logs.Error(err)
|
logs.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -92,7 +110,6 @@ func (s *TRPClient) newUdpConn(rAddr string, md5Password string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logs.Trace("start local p2p udp listen, local address", localConn.LocalAddr().String())
|
logs.Trace("start local p2p udp listen, local address", localConn.LocalAddr().String())
|
||||||
//接收新的监听,得到conn,
|
|
||||||
for {
|
for {
|
||||||
udpTunnel, err := l.AcceptKCP()
|
udpTunnel, err := l.AcceptKCP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -104,14 +121,10 @@ func (s *TRPClient) newUdpConn(rAddr string, md5Password string) {
|
||||||
conn.SetUdpSession(udpTunnel)
|
conn.SetUdpSession(udpTunnel)
|
||||||
logs.Trace("successful connection with client ,address %s", udpTunnel.RemoteAddr().String())
|
logs.Trace("successful connection with client ,address %s", udpTunnel.RemoteAddr().String())
|
||||||
//read link info from remote
|
//read link info from remote
|
||||||
l := mux.NewMux(udpTunnel, s.bridgeConnType)
|
conn.Accept(mux.NewMux(udpTunnel, s.bridgeConnType), func(c net.Conn) {
|
||||||
for {
|
go s.handleChan(c)
|
||||||
connMux, err := l.Accept()
|
})
|
||||||
if err != nil {
|
break
|
||||||
continue
|
|
||||||
}
|
|
||||||
go s.handleChan(connMux)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +157,31 @@ func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
}
|
}
|
||||||
//host for target processing
|
//host for target processing
|
||||||
lk.Host = common.FormatAddress(lk.Host)
|
lk.Host = common.FormatAddress(lk.Host)
|
||||||
//connect to target
|
//if Conn type is http, read the request and log
|
||||||
|
if lk.ConnType == "http" {
|
||||||
|
if targetConn, err := net.Dial(common.CONN_TCP, lk.Host); err != nil {
|
||||||
|
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
||||||
|
src.Close()
|
||||||
|
} else {
|
||||||
|
go func() {
|
||||||
|
common.CopyBuffer(src, targetConn)
|
||||||
|
src.Close()
|
||||||
|
targetConn.Close()
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
if r, err := http.ReadRequest(bufio.NewReader(src)); err != nil {
|
||||||
|
src.Close()
|
||||||
|
targetConn.Close()
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
logs.Trace("http request, method %s, host %s, url %s, remote address %s", r.Method, r.Host, r.URL.Path, r.RemoteAddr)
|
||||||
|
r.Write(targetConn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//connect to target if conn type is tcp or udp
|
||||||
if targetConn, err := net.Dial(lk.ConnType, lk.Host); err != nil {
|
if targetConn, err := net.Dial(lk.ConnType, lk.Host); err != nil {
|
||||||
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
||||||
src.Close()
|
src.Close()
|
||||||
|
@ -154,6 +191,7 @@ func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the monitor channel is closed
|
||||||
func (s *TRPClient) ping() {
|
func (s *TRPClient) ping() {
|
||||||
s.ticker = time.NewTicker(time.Second * 5)
|
s.ticker = time.NewTicker(time.Second * 5)
|
||||||
loop:
|
loop:
|
||||||
|
|
|
@ -4,17 +4,19 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"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/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/version"
|
"github.com/cnlh/nps/lib/version"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"github.com/cnlh/nps/vender/github.com/ccding/go-stun/stun"
|
|
||||||
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"github.com/cnlh/nps/vender/golang.org/x/net/proxy"
|
"github.com/cnlh/nps/vender/golang.org/x/net/proxy"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
@ -276,108 +278,137 @@ func basicAuth(username, password string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(auth))
|
return base64.StdEncoding.EncodeToString([]byte(auth))
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleP2PUdp(rAddr, md5Password, role string) (remoteAddress string, c net.PacketConn, err error) {
|
func getRemoteAddressFromServer(rAddr string, localConn *net.UDPConn, md5Password, role string, add int) error {
|
||||||
tmpConn, err := common.GetLocalUdpAddr()
|
rAddr, err := getNextAddr(rAddr, add)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error(err)
|
logs.Error(err)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
localConn, err := newUdpConnByAddr(tmpConn.LocalAddr().String())
|
addr, err := net.ResolveUDPAddr("udp", rAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error(err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
localKcpConn, err := kcp.NewConn(rAddr, nil, 150, 3, localConn)
|
if _, err := localConn.WriteTo(common.GetWriteStr(md5Password, role), addr); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
logs.Error(err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
conn.SetUdpSession(localKcpConn)
|
return nil
|
||||||
localToolConn := conn.NewConn(localKcpConn)
|
|
||||||
//get local nat type
|
|
||||||
//localNatType, host, err := stun.NewClient().Discover()
|
|
||||||
//if err != nil || host == nil {
|
|
||||||
// err = errors.New("get nat type error")
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
localNatType := stun.NATRestricted
|
|
||||||
//write password
|
|
||||||
if _, err = localToolConn.Write([]byte(md5Password)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//write role
|
|
||||||
if _, err = localToolConn.Write([]byte(role)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = binary.Write(localToolConn, binary.LittleEndian, int32(localNatType)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//get another type address and nat type from server
|
|
||||||
var remoteAddr []byte
|
|
||||||
var remoteNatType int32
|
|
||||||
if remoteAddr, err = localToolConn.GetShortLenContent(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = binary.Read(localToolConn, binary.LittleEndian, &remoteNatType); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
localConn.Close()
|
|
||||||
//logs.Trace("remote nat type %d,local nat type %s", remoteNatType, localNatType)
|
|
||||||
if remoteAddress, err = sendP2PTestMsg(string(remoteAddr), tmpConn.LocalAddr().String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c, err = newUdpConnByAddr(tmpConn.LocalAddr().String())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleP2P(natType1, natType2 int, addr1, addr2 string, role string) (string, error) {
|
func handleP2PUdp(localAddr, rAddr, md5Password, role string) (remoteAddress string, c net.PacketConn, err error) {
|
||||||
switch natType1 {
|
|
||||||
case int(stun.NATFull):
|
|
||||||
return sendP2PTestMsg(addr2, addr1)
|
|
||||||
case int(stun.NATRestricted):
|
|
||||||
switch natType2 {
|
|
||||||
case int(stun.NATFull), int(stun.NATRestricted), int(stun.NATPortRestricted), int(stun.NATSymetric):
|
|
||||||
return sendP2PTestMsg(addr2, addr1)
|
|
||||||
}
|
|
||||||
case int(stun.NATPortRestricted):
|
|
||||||
switch natType2 {
|
|
||||||
case int(stun.NATFull), int(stun.NATRestricted), int(stun.NATPortRestricted):
|
|
||||||
return sendP2PTestMsg(addr2, addr1)
|
|
||||||
}
|
|
||||||
case int(stun.NATSymetric):
|
|
||||||
switch natType2 {
|
|
||||||
case int(stun.NATFull), int(stun.NATRestricted):
|
|
||||||
return sendP2PTestMsg(addr2, addr1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", errors.New("not support p2p")
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendP2PTestMsg(remoteAddr string, localAddr string) (string, error) {
|
|
||||||
remoteUdpAddr, err := net.ResolveUDPAddr("udp", remoteAddr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
localConn, err := newUdpConnByAddr(localAddr)
|
localConn, err := newUdpConnByAddr(localAddr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = getRemoteAddressFromServer(rAddr, localConn, md5Password, role, 0)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = getRemoteAddressFromServer(rAddr, localConn, md5Password, role, 1)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = getRemoteAddressFromServer(rAddr, localConn, md5Password, role, 2)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var remoteAddr1, remoteAddr2, remoteAddr3 string
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
if n, addr, er := localConn.ReadFromUDP(buf); er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
rAddr2, _ := getNextAddr(rAddr, 1)
|
||||||
|
rAddr3, _ := getNextAddr(rAddr, 2)
|
||||||
|
switch addr.String() {
|
||||||
|
case rAddr:
|
||||||
|
remoteAddr1 = string(buf[:n])
|
||||||
|
case rAddr2:
|
||||||
|
remoteAddr2 = string(buf[:n])
|
||||||
|
case rAddr3:
|
||||||
|
remoteAddr3 = string(buf[:n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if remoteAddr1 != "" && remoteAddr2 != "" && remoteAddr3 != "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if remoteAddress, err = sendP2PTestMsg(localConn, remoteAddr1, remoteAddr2, remoteAddr3); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, err = newUdpConnByAddr(localAddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendP2PTestMsg(localConn *net.UDPConn, remoteAddr1, remoteAddr2, remoteAddr3 string) (string, error) {
|
||||||
|
logs.Trace(remoteAddr3, remoteAddr2, remoteAddr1)
|
||||||
|
defer localConn.Close()
|
||||||
|
isClose := false
|
||||||
|
defer func() { isClose = true }()
|
||||||
|
interval, err := getAddrInterval(remoteAddr1, remoteAddr2, remoteAddr3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer localConn.Close()
|
go func() {
|
||||||
|
addr, err := getNextAddr(remoteAddr3, interval)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
remoteUdpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logs.Trace("try send test packet to target %s", addr)
|
||||||
ticker := time.NewTicker(time.Millisecond * 500)
|
ticker := time.NewTicker(time.Millisecond * 500)
|
||||||
go func(ticker *time.Ticker) {
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
logs.Trace("try send test packet to target %s", remoteAddr)
|
if isClose {
|
||||||
|
return
|
||||||
|
}
|
||||||
if _, err := localConn.WriteTo([]byte(common.WORK_P2P_CONNECT), remoteUdpAddr); err != nil {
|
if _, err := localConn.WriteTo([]byte(common.WORK_P2P_CONNECT), remoteUdpAddr); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(ticker)
|
}()
|
||||||
|
if interval != 0 {
|
||||||
|
ip := common.GetIpByAddr(remoteAddr2)
|
||||||
|
go func() {
|
||||||
|
ports := getRandomPortArr(common.GetPortByAddr(remoteAddr3), common.GetPortByAddr(remoteAddr3)+interval*50)
|
||||||
|
for i := 0; i <= 50; i ++ {
|
||||||
|
go func(port int) {
|
||||||
|
trueAddress := ip + ":" + strconv.Itoa(port)
|
||||||
|
logs.Trace("try send test packet to target %s", trueAddress)
|
||||||
|
remoteUdpAddr, err := net.ResolveUDPAddr("udp", trueAddress)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ticker := time.NewTicker(time.Second * 2)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
if isClose {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := localConn.WriteTo([]byte(common.WORK_P2P_CONNECT), remoteUdpAddr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(ports[i])
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
buf := make([]byte, 10)
|
buf := make([]byte, 10)
|
||||||
for {
|
for {
|
||||||
localConn.SetReadDeadline(time.Now().Add(time.Second * 30))
|
localConn.SetReadDeadline(time.Now().Add(time.Second * 10))
|
||||||
n, addr, err := localConn.ReadFromUDP(buf)
|
n, addr, err := localConn.ReadFromUDP(buf)
|
||||||
localConn.SetReadDeadline(time.Time{})
|
localConn.SetReadDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -397,7 +428,7 @@ func sendP2PTestMsg(remoteAddr string, localAddr string) (string, error) {
|
||||||
case common.WORK_P2P_CONNECT:
|
case common.WORK_P2P_CONNECT:
|
||||||
go func() {
|
go func() {
|
||||||
for i := 20; i > 0; i-- {
|
for i := 20; i > 0; i-- {
|
||||||
logs.Trace("try send receive success packet to target %s", remoteAddr)
|
logs.Trace("try send receive success packet to target %s", addr.String())
|
||||||
if _, err = localConn.WriteTo([]byte(common.WORK_P2P_SUCCESS), addr); err != nil {
|
if _, err = localConn.WriteTo([]byte(common.WORK_P2P_SUCCESS), addr); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -407,9 +438,7 @@ func sendP2PTestMsg(remoteAddr string, localAddr string) (string, error) {
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ticker.Stop()
|
|
||||||
}
|
}
|
||||||
ticker.Stop()
|
|
||||||
return "", errors.New("connect to the target failed, maybe the nat type is not support p2p")
|
return "", errors.New("connect to the target failed, maybe the nat type is not support p2p")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,3 +453,66 @@ func newUdpConnByAddr(addr string) (*net.UDPConn, error) {
|
||||||
}
|
}
|
||||||
return udpConn, nil
|
return udpConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNextAddr(addr string, n int) (string, error) {
|
||||||
|
arr := strings.Split(addr, ":")
|
||||||
|
if len(arr) != 2 {
|
||||||
|
return "", errors.New(fmt.Sprintf("the format of %s incorrect", addr))
|
||||||
|
}
|
||||||
|
if p, err := strconv.Atoi(arr[1]); err != nil {
|
||||||
|
return "", err
|
||||||
|
} else {
|
||||||
|
return arr[0] + ":" + strconv.Itoa(p+n), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAddrInterval(addr1, addr2, addr3 string) (int, error) {
|
||||||
|
arr1 := strings.Split(addr1, ":")
|
||||||
|
if len(arr1) != 2 {
|
||||||
|
return 0, errors.New(fmt.Sprintf("the format of %s incorrect", addr1))
|
||||||
|
}
|
||||||
|
arr2 := strings.Split(addr2, ":")
|
||||||
|
if len(arr2) != 2 {
|
||||||
|
return 0, errors.New(fmt.Sprintf("the format of %s incorrect", addr2))
|
||||||
|
}
|
||||||
|
arr3 := strings.Split(addr3, ":")
|
||||||
|
if len(arr3) != 2 {
|
||||||
|
return 0, errors.New(fmt.Sprintf("the format of %s incorrect", addr3))
|
||||||
|
}
|
||||||
|
p1, err := strconv.Atoi(arr1[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
p2, err := strconv.Atoi(arr2[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
p3, err := strconv.Atoi(arr3[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
interVal := int(math.Floor(math.Min(math.Abs(float64(p3-p2)), math.Abs(float64(p2-p1)))))
|
||||||
|
if p3-p1 < 0 {
|
||||||
|
return -interVal, nil
|
||||||
|
}
|
||||||
|
return interVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRandomPortArr(min, max int) []int {
|
||||||
|
if min > max {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
addrAddr := make([]int, max-min+1)
|
||||||
|
for i := min; i <= max; i++ {
|
||||||
|
addrAddr[max-i] = i
|
||||||
|
}
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
var r, temp int
|
||||||
|
for i := max - min; i > 0; i-- {
|
||||||
|
r = rand.Int() % i
|
||||||
|
temp = addrAddr[i]
|
||||||
|
addrAddr[i] = addrAddr[r]
|
||||||
|
addrAddr[r] = temp
|
||||||
|
}
|
||||||
|
return addrAddr
|
||||||
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"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/mux"
|
"github.com/cnlh/nps/lib/mux"
|
||||||
|
"github.com/cnlh/nps/server/proxy"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -19,10 +19,24 @@ var (
|
||||||
udpConn net.Conn
|
udpConn net.Conn
|
||||||
muxSession *mux.Mux
|
muxSession *mux.Mux
|
||||||
fileServer []*http.Server
|
fileServer []*http.Server
|
||||||
lock sync.Mutex
|
p2pNetBridge *p2pBridge
|
||||||
hasP2PTry bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type p2pBridge struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p2pBridge *p2pBridge) SendLinkInfo(clientId int, link *conn.Link, t *file.Tunnel) (target net.Conn, err error) {
|
||||||
|
nowConn, err := muxSession.NewConn()
|
||||||
|
if err != nil {
|
||||||
|
udpConn = nil
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, err := conn.NewConn(nowConn).SendInfo(link, ""); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nowConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
func CloseLocalServer() {
|
func CloseLocalServer() {
|
||||||
for _, v := range LocalServer {
|
for _, v := range LocalServer {
|
||||||
v.Close()
|
v.Close()
|
||||||
|
@ -48,20 +62,58 @@ func startLocalFileServer(config *config.CommonConfig, t *file.Tunnel, vkey stri
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartLocalServer(l *config.LocalServer, config *config.CommonConfig) error {
|
func StartLocalServer(l *config.LocalServer, config *config.CommonConfig) error {
|
||||||
|
tmpConn, err := common.GetLocalUdpAddr()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
logs.Notice("try to connect to the server", i+1)
|
||||||
|
newUdpConn(tmpConn.LocalAddr().String(), config, l)
|
||||||
|
if udpConn != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task := &file.Tunnel{
|
||||||
|
Port: l.Port,
|
||||||
|
ServerIp: "0.0.0.0",
|
||||||
|
Status: true,
|
||||||
|
Client: &file.Client{
|
||||||
|
Cnf: &file.Config{
|
||||||
|
U: "",
|
||||||
|
P: "",
|
||||||
|
Compress: config.Client.Cnf.Compress,
|
||||||
|
},
|
||||||
|
Status: true,
|
||||||
|
RateLimit: 0,
|
||||||
|
Flow: &file.Flow{},
|
||||||
|
},
|
||||||
|
Flow: &file.Flow{},
|
||||||
|
Target: &file.Target{},
|
||||||
|
}
|
||||||
|
switch l.Type {
|
||||||
|
case "p2ps":
|
||||||
|
logs.Info("successful start-up of local socks5 monitoring, port", l.Port)
|
||||||
|
return proxy.NewSock5ModeServer(p2pNetBridge, task).Start()
|
||||||
|
case "p2pt":
|
||||||
|
logs.Info("successful start-up of local tcp trans monitoring, port", l.Port)
|
||||||
|
return proxy.NewTunnelModeServer(proxy.HandleTrans, p2pNetBridge, task).Start()
|
||||||
|
case "p2p", "secret":
|
||||||
listener, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), l.Port, ""})
|
listener, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), l.Port, ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error("local listener startup failed port %d, error %s", l.Port, err.Error())
|
logs.Error("local listener startup failed port %d, error %s", l.Port, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
LocalServer = append(LocalServer, listener)
|
LocalServer = append(LocalServer, listener)
|
||||||
logs.Info("successful start-up of local monitoring, port", l.Port)
|
logs.Info("successful start-up of local tcp monitoring, port", l.Port)
|
||||||
conn.Accept(listener, func(c net.Conn) {
|
conn.Accept(listener, func(c net.Conn) {
|
||||||
|
logs.Trace("new %s connection", l.Type)
|
||||||
if l.Type == "secret" {
|
if l.Type == "secret" {
|
||||||
handleSecret(c, config, l)
|
handleSecret(c, config, l)
|
||||||
} else {
|
} else if l.Type == "p2p" {
|
||||||
handleP2PVisitor(c, config, l)
|
handleP2PVisitor(c, config, l)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,41 +131,22 @@ func handleSecret(localTcpConn net.Conn, config *config.CommonConfig, l *config.
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleP2PVisitor(localTcpConn net.Conn, config *config.CommonConfig, l *config.LocalServer) {
|
func handleP2PVisitor(localTcpConn net.Conn, config *config.CommonConfig, l *config.LocalServer) {
|
||||||
restart:
|
|
||||||
lock.Lock()
|
|
||||||
if udpConn == nil {
|
if udpConn == nil {
|
||||||
if !hasP2PTry {
|
|
||||||
hasP2PTry = true
|
|
||||||
newUdpConn(config, l)
|
|
||||||
}
|
|
||||||
if udpConn == nil {
|
|
||||||
lock.Unlock()
|
|
||||||
logs.Notice("new conn, P2P can not penetrate successfully, traffic will be transferred through the server")
|
logs.Notice("new conn, P2P can not penetrate successfully, traffic will be transferred through the server")
|
||||||
handleSecret(localTcpConn, config, l)
|
handleSecret(localTcpConn, config, l)
|
||||||
return
|
|
||||||
} else {
|
|
||||||
muxSession = mux.NewMux(udpConn, "kcp")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
lock.Unlock()
|
|
||||||
logs.Trace("start trying to connect with the server")
|
logs.Trace("start trying to connect with the server")
|
||||||
nowConn, err := muxSession.NewConn()
|
|
||||||
if err != nil {
|
|
||||||
udpConn = nil
|
|
||||||
logs.Error(err, "reconnect......")
|
|
||||||
goto restart
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//TODO just support compress now because there is not tls file in client packages
|
//TODO just support compress now because there is not tls file in client packages
|
||||||
link := conn.NewLink(common.CONN_TCP, l.Target, false, config.Client.Cnf.Compress, localTcpConn.LocalAddr().String(), false)
|
link := conn.NewLink(common.CONN_TCP, l.Target, false, config.Client.Cnf.Compress, localTcpConn.LocalAddr().String(), false)
|
||||||
if _, err := conn.NewConn(nowConn).SendInfo(link, ""); err != nil {
|
if target, err := p2pNetBridge.SendLinkInfo(0, link, nil); err != nil {
|
||||||
logs.Error(err)
|
logs.Error(err)
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
conn.CopyWaitGroup(target, localTcpConn, false, config.Client.Cnf.Compress, nil, nil, false, nil)
|
||||||
}
|
}
|
||||||
conn.CopyWaitGroup(nowConn, localTcpConn, false, config.Client.Cnf.Compress, nil, nil, false, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUdpConn(config *config.CommonConfig, l *config.LocalServer) {
|
func newUdpConn(localAddr string, config *config.CommonConfig, l *config.LocalServer) {
|
||||||
remoteConn, err := NewConn(config.Tp, config.VKey, config.Server, common.WORK_P2P, config.ProxyUrl)
|
remoteConn, err := NewConn(config.Tp, config.VKey, config.Server, common.WORK_P2P, config.ProxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error("Local connection server failed ", err.Error())
|
logs.Error("Local connection server failed ", err.Error())
|
||||||
|
@ -131,7 +164,7 @@ func newUdpConn(config *config.CommonConfig, l *config.LocalServer) {
|
||||||
}
|
}
|
||||||
var localConn net.PacketConn
|
var localConn net.PacketConn
|
||||||
var remoteAddress string
|
var remoteAddress string
|
||||||
if remoteAddress, localConn, err = handleP2PUdp(string(rAddr), crypt.Md5(l.Password), common.WORK_P2P_VISITOR); err != nil {
|
if remoteAddress, localConn, err = handleP2PUdp(localAddr, string(rAddr), crypt.Md5(l.Password), common.WORK_P2P_VISITOR); err != nil {
|
||||||
logs.Error(err)
|
logs.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -143,4 +176,6 @@ func newUdpConn(config *config.CommonConfig, l *config.LocalServer) {
|
||||||
logs.Trace("successful create a connection with server", remoteAddress)
|
logs.Trace("successful create a connection with server", remoteAddress)
|
||||||
conn.SetUdpSession(udpTunnel)
|
conn.SetUdpSession(udpTunnel)
|
||||||
udpConn = udpTunnel
|
udpConn = udpTunnel
|
||||||
|
muxSession = mux.NewMux(udpConn, "kcp")
|
||||||
|
p2pNetBridge = &p2pBridge{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func main() {
|
||||||
if *logType == "stdout" {
|
if *logType == "stdout" {
|
||||||
logs.SetLogger(logs.AdapterConsole, `{"level":`+*logLevel+`,"color":true}`)
|
logs.SetLogger(logs.AdapterConsole, `{"level":`+*logLevel+`,"color":true}`)
|
||||||
} else {
|
} else {
|
||||||
logs.SetLogger(logs.AdapterFile, `{"level":`+*logLevel+`,"filename":"`+*logPath+`","daily":false,"color":true}`)
|
logs.SetLogger(logs.AdapterFile, `{"level":`+*logLevel+`,"filename":"`+*logPath+`","daily":false,"maxlines":100000,"color":true}`)
|
||||||
}
|
}
|
||||||
//p2p or secret command
|
//p2p or secret command
|
||||||
if *password != "" {
|
if *password != "" {
|
||||||
|
|
|
@ -50,7 +50,7 @@ func main() {
|
||||||
if *logType == "stdout" {
|
if *logType == "stdout" {
|
||||||
logs.SetLogger(logs.AdapterConsole, `{"level":`+level+`,"color":true}`)
|
logs.SetLogger(logs.AdapterConsole, `{"level":`+level+`,"color":true}`)
|
||||||
} else {
|
} else {
|
||||||
logs.SetLogger(logs.AdapterFile, `{"level":`+level+`,"filename":"`+beego.AppConfig.String("log_path")+`","daily":false,"color":true}`)
|
logs.SetLogger(logs.AdapterFile, `{"level":`+level+`,"filename":"`+beego.AppConfig.String("log_path")+`","daily":false,"maxlines":100000,"color":true}`)
|
||||||
}
|
}
|
||||||
task := &file.Tunnel{
|
task := &file.Tunnel{
|
||||||
Mode: "webServer",
|
Mode: "webServer",
|
||||||
|
|
|
@ -163,6 +163,13 @@ func TestUdpPort(port int) bool {
|
||||||
//Length prevents sticking
|
//Length prevents sticking
|
||||||
//# Characters are used to separate data
|
//# Characters are used to separate data
|
||||||
func BinaryWrite(raw *bytes.Buffer, v ...string) {
|
func BinaryWrite(raw *bytes.Buffer, v ...string) {
|
||||||
|
b := GetWriteStr(v...)
|
||||||
|
binary.Write(raw, binary.LittleEndian, int32(len(b)))
|
||||||
|
binary.Write(raw, binary.LittleEndian, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get seq str
|
||||||
|
func GetWriteStr(v ...string) []byte {
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
var l int32
|
var l int32
|
||||||
for _, v := range v {
|
for _, v := range v {
|
||||||
|
@ -170,8 +177,7 @@ func BinaryWrite(raw *bytes.Buffer, v ...string) {
|
||||||
binary.Write(buffer, binary.LittleEndian, []byte(v))
|
binary.Write(buffer, binary.LittleEndian, []byte(v))
|
||||||
binary.Write(buffer, binary.LittleEndian, []byte(CONN_DATA_SEQ))
|
binary.Write(buffer, binary.LittleEndian, []byte(CONN_DATA_SEQ))
|
||||||
}
|
}
|
||||||
binary.Write(raw, binary.LittleEndian, l)
|
return buffer.Bytes()
|
||||||
binary.Write(raw, binary.LittleEndian, buffer.Bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//inArray str interface
|
//inArray str interface
|
||||||
|
@ -244,6 +250,19 @@ func GetIpByAddr(addr string) string {
|
||||||
return arr[0]
|
return arr[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get port from the complete address
|
||||||
|
func GetPortByAddr(addr string) int {
|
||||||
|
arr := strings.Split(addr, ":")
|
||||||
|
if len(arr) < 2 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
p, err := strconv.Atoi(arr[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||||
buf := pool.GetBufPoolCopy()
|
buf := pool.GetBufPoolCopy()
|
||||||
defer pool.PutBufPoolCopy(buf)
|
defer pool.PutBufPoolCopy(buf)
|
||||||
|
|
|
@ -13,6 +13,9 @@ import (
|
||||||
|
|
||||||
func InstallNps() {
|
func InstallNps() {
|
||||||
path := common.GetInstallPath()
|
path := common.GetInstallPath()
|
||||||
|
if common.FileExists(path) {
|
||||||
|
log.Fatalf("the path %s has exist, does not support install", path)
|
||||||
|
}
|
||||||
MkidrDirAll(path, "conf", "web/static", "web/views")
|
MkidrDirAll(path, "conf", "web/static", "web/views")
|
||||||
//复制文件到对应目录
|
//复制文件到对应目录
|
||||||
if err := CopyDir(filepath.Join(common.GetAppPath(), "web", "views"), filepath.Join(path, "web", "views")); err != nil {
|
if err := CopyDir(filepath.Join(common.GetAppPath(), "web", "views"), filepath.Join(path, "web", "views")); err != nil {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package version
|
package version
|
||||||
|
|
||||||
const VERSION = "0.22.5"
|
const VERSION = "0.23.0"
|
||||||
|
|
||||||
// Compulsory minimum version, Minimum downward compatibility to this version
|
// Compulsory minimum version, Minimum downward compatibility to this version
|
||||||
func GetVersion() string {
|
func GetVersion() string {
|
||||||
|
|
|
@ -17,10 +17,14 @@ type Service interface {
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NetBridge interface {
|
||||||
|
SendLinkInfo(clientId int, link *conn.Link, t *file.Tunnel) (target net.Conn, err error)
|
||||||
|
}
|
||||||
|
|
||||||
//BaseServer struct
|
//BaseServer struct
|
||||||
type BaseServer struct {
|
type BaseServer struct {
|
||||||
id int
|
id int
|
||||||
bridge *bridge.Bridge
|
bridge NetBridge
|
||||||
task *file.Tunnel
|
task *file.Tunnel
|
||||||
errorContent []byte
|
errorContent []byte
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
|
@ -147,7 +147,7 @@ func (s *httpServer) httpHandle(c *conn.Conn, r *http.Request) {
|
||||||
logs.Warn(err.Error())
|
logs.Warn(err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lk = conn.NewLink(common.CONN_TCP, targetAddr, host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr, host.Target.LocalProxy)
|
lk = conn.NewLink("http", targetAddr, host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr, host.Target.LocalProxy)
|
||||||
if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, nil); err != nil {
|
if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, nil); err != nil {
|
||||||
logs.Notice("connect to target %s error %s", lk.Host, err)
|
logs.Notice("connect to target %s error %s", lk.Host, err)
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/bridge"
|
|
||||||
"github.com/cnlh/nps/lib/cache"
|
"github.com/cnlh/nps/lib/cache"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
|
@ -22,7 +21,7 @@ type HttpsServer struct {
|
||||||
httpsListenerMap sync.Map
|
httpsListenerMap sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpsServer(l net.Listener, bridge *bridge.Bridge, useCache bool, cacheLen int) *HttpsServer {
|
func NewHttpsServer(l net.Listener, bridge NetBridge, useCache bool, cacheLen int) *HttpsServer {
|
||||||
https := &HttpsServer{listener: l}
|
https := &HttpsServer{listener: l}
|
||||||
https.bridge = bridge
|
https.bridge = bridge
|
||||||
https.useCache = useCache
|
https.useCache = useCache
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,15 +13,12 @@ type P2PServer struct {
|
||||||
BaseServer
|
BaseServer
|
||||||
p2pPort int
|
p2pPort int
|
||||||
p2p map[string]*p2p
|
p2p map[string]*p2p
|
||||||
|
listener *net.UDPConn
|
||||||
}
|
}
|
||||||
|
|
||||||
type p2p struct {
|
type p2p struct {
|
||||||
provider *conn.Conn
|
visitorAddr *net.UDPAddr
|
||||||
visitor *conn.Conn
|
providerAddr *net.UDPAddr
|
||||||
visitorAddr string
|
|
||||||
providerAddr string
|
|
||||||
providerNatType int32
|
|
||||||
visitorNatType int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewP2PServer(p2pPort int) *P2PServer {
|
func NewP2PServer(p2pPort int) *P2PServer {
|
||||||
|
@ -33,62 +29,52 @@ func NewP2PServer(p2pPort int) *P2PServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *P2PServer) Start() error {
|
func (s *P2PServer) Start() error {
|
||||||
return conn.NewKcpListenerAndProcess(":"+strconv.Itoa(s.p2pPort), func(c net.Conn) {
|
logs.Info("start p2p server port", s.p2pPort)
|
||||||
s.p2pProcess(conn.NewConn(c))
|
var err error
|
||||||
})
|
s.listener, err = net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), s.p2pPort, ""})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
buf := pool.BufPoolUdp.Get().([]byte)
|
||||||
|
n, addr, err := s.listener.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go s.handleP2P(addr, string(buf[:n]))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *P2PServer) p2pProcess(c *conn.Conn) {
|
func (s *P2PServer) handleP2P(addr *net.UDPAddr, str string) {
|
||||||
var (
|
var (
|
||||||
f string
|
|
||||||
b []byte
|
|
||||||
err error
|
|
||||||
v *p2p
|
v *p2p
|
||||||
ok bool
|
ok bool
|
||||||
natType int32
|
|
||||||
)
|
)
|
||||||
if b, err = c.GetShortContent(32); err != nil {
|
arr := strings.Split(str, common.CONN_DATA_SEQ)
|
||||||
|
if len(arr) < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//get role
|
if v, ok = s.p2p[arr[0]]; !ok {
|
||||||
if f, err = c.ReadFlag(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//get nat type
|
|
||||||
if err := binary.Read(c, binary.LittleEndian, &natType); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v, ok = s.p2p[string(b)]; !ok {
|
|
||||||
v = new(p2p)
|
v = new(p2p)
|
||||||
s.p2p[string(b)] = v
|
s.p2p[arr[0]] = v
|
||||||
}
|
}
|
||||||
logs.Trace("new p2p connection ,role %s , password %s, nat type %s ,local address %s", f, string(b), strconv.Itoa(int(natType)), c.RemoteAddr().String())
|
logs.Trace("new p2p connection ,role %s , password %s ,local address %s", arr[1], arr[0], addr.String())
|
||||||
//存储
|
if arr[1] == common.WORK_P2P_VISITOR {
|
||||||
if f == common.WORK_P2P_VISITOR {
|
v.visitorAddr = addr
|
||||||
v.visitorAddr = c.Conn.RemoteAddr().String()
|
|
||||||
v.visitorNatType = natType
|
|
||||||
v.visitor = c
|
|
||||||
for i := 20; i > 0; i-- {
|
for i := 20; i > 0; i-- {
|
||||||
if v.provider != nil {
|
if v.providerAddr != nil {
|
||||||
v.provider.WriteLenContent([]byte(v.visitorAddr))
|
s.listener.WriteTo([]byte(v.providerAddr.String()), v.visitorAddr)
|
||||||
binary.Write(v.provider, binary.LittleEndian, v.visitorNatType)
|
s.listener.WriteTo([]byte(v.visitorAddr.String()), v.providerAddr)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
v.provider = nil
|
delete(s.p2p, arr[0])
|
||||||
} else {
|
} else {
|
||||||
v.providerAddr = c.Conn.RemoteAddr().String()
|
v.providerAddr = addr
|
||||||
v.providerNatType = natType
|
|
||||||
v.provider = c
|
|
||||||
for i := 20; i > 0; i-- {
|
|
||||||
if v.visitor != nil {
|
|
||||||
v.visitor.WriteLenContent([]byte(v.providerAddr))
|
|
||||||
binary.Write(v.visitor, binary.LittleEndian, v.providerNatType)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
v.visitor = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package proxy
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/bridge"
|
|
||||||
"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"
|
||||||
|
@ -264,7 +263,7 @@ func (s *Sock5ModeServer) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//new
|
//new
|
||||||
func NewSock5ModeServer(bridge *bridge.Bridge, task *file.Tunnel) *Sock5ModeServer {
|
func NewSock5ModeServer(bridge NetBridge, task *file.Tunnel) *Sock5ModeServer {
|
||||||
s := new(Sock5ModeServer)
|
s := new(Sock5ModeServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
s.task = task
|
s.task = task
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunnelModeServer struct {
|
type TunnelModeServer struct {
|
||||||
|
@ -22,7 +23,7 @@ type TunnelModeServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//tcp|http|host
|
//tcp|http|host
|
||||||
func NewTunnelModeServer(process process, bridge *bridge.Bridge, task *file.Tunnel) *TunnelModeServer {
|
func NewTunnelModeServer(process process, bridge NetBridge, task *file.Tunnel) *TunnelModeServer {
|
||||||
s := new(TunnelModeServer)
|
s := new(TunnelModeServer)
|
||||||
s.bridge = bridge
|
s.bridge = bridge
|
||||||
s.process = process
|
s.process = process
|
||||||
|
@ -114,3 +115,35 @@ func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
}
|
}
|
||||||
return s.DealClient(c, s.task.Client, addr, rb, common.CONN_TCP, nil, s.task.Flow, s.task.Target.LocalProxy)
|
return s.DealClient(c, s.task.Client, addr, rb, common.CONN_TCP, nil, s.task.Flow, s.task.Target.LocalProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleTrans(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
|
if addr, err := getAddress(c.Conn); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return s.DealClient(c, s.task.Client, addr, nil, common.CONN_TCP, nil, s.task.Flow, s.task.Target.LocalProxy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SO_ORIGINAL_DST = 80
|
||||||
|
|
||||||
|
func getAddress(conn net.Conn) (string, error) {
|
||||||
|
sysrawconn, f := conn.(syscall.Conn)
|
||||||
|
if !f {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
rawConn, err := sysrawconn.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
var ip string
|
||||||
|
var port uint16
|
||||||
|
err = rawConn.Control(func(fd uintptr) {
|
||||||
|
addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ip = net.IP(addr.Multiaddr[4:8]).String()
|
||||||
|
port = uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3])
|
||||||
|
})
|
||||||
|
return ip + ":" + strconv.Itoa(int(port)), nil
|
||||||
|
}
|
||||||
|
|
|
@ -90,8 +90,9 @@ func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if p, err := beego.AppConfig.Int("p2p_port"); err == nil {
|
if p, err := beego.AppConfig.Int("p2p_port"); err == nil {
|
||||||
logs.Info("start p2p server port", p)
|
|
||||||
go proxy.NewP2PServer(p).Start()
|
go proxy.NewP2PServer(p).Start()
|
||||||
|
go proxy.NewP2PServer(p + 1).Start()
|
||||||
|
go proxy.NewP2PServer(p + 2).Start()
|
||||||
}
|
}
|
||||||
go DealBridgeTask()
|
go DealBridgeTask()
|
||||||
go dealClientFlow()
|
go dealClientFlow()
|
||||||
|
@ -125,6 +126,8 @@ func NewMode(Bridge *bridge.Bridge, c *file.Tunnel) proxy.Service {
|
||||||
service = proxy.NewSock5ModeServer(Bridge, c)
|
service = proxy.NewSock5ModeServer(Bridge, c)
|
||||||
case "httpProxy":
|
case "httpProxy":
|
||||||
service = proxy.NewTunnelModeServer(proxy.ProcessHttp, Bridge, c)
|
service = proxy.NewTunnelModeServer(proxy.ProcessHttp, Bridge, c)
|
||||||
|
case "tcpTrans":
|
||||||
|
service = proxy.NewTunnelModeServer(proxy.HandleTrans, Bridge, c)
|
||||||
case "udp":
|
case "udp":
|
||||||
service = proxy.NewUdpModeServer(Bridge, c)
|
service = proxy.NewUdpModeServer(Bridge, c)
|
||||||
case "webServer":
|
case "webServer":
|
||||||
|
|
|
@ -70,7 +70,11 @@
|
||||||
+ '<b langtag="info-web-auth-username">basic权限认证用户名</b>:' + row.Client.Cnf.U + `       `
|
+ '<b langtag="info-web-auth-username">basic权限认证用户名</b>:' + row.Client.Cnf.U + `       `
|
||||||
+ '<b langtag="info-web-auth-password">basic权限认证密码</b>:' + row.Client.Cnf.P + `       `
|
+ '<b langtag="info-web-auth-password">basic权限认证密码</b>:' + row.Client.Cnf.P + `       `
|
||||||
if (row.Mode == "p2p") {
|
if (row.Mode == "p2p") {
|
||||||
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -target=" + row.Target.TargetStr + "</code>"
|
return tmp + "<br/><br>"
|
||||||
|
+ '<b langtag="info-command">访问端命令(tcp)</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -target=" + row.Target.TargetStr + "</code>" + "<br/><br>"
|
||||||
|
+ '<b langtag="info-command">访问端命令(socks5)</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=p2ps" + "</code>" + "<br/><br>"
|
||||||
|
+ '<b langtag="info-command">访问端命令(透明代理)</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=p2pt" + "</code>"
|
||||||
|
|
||||||
}
|
}
|
||||||
if (row.Mode = "secret") {
|
if (row.Mode = "secret") {
|
||||||
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=secret" + "</code>"
|
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>:' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=secret" + "</code>"
|
||||||
|
|
Loading…
Reference in New Issue