Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>

This commit is contained in:
arraykeys@gmail.com
2017-10-09 15:11:34 +08:00
parent 5fa000f7e6
commit f270885a4d
9 changed files with 69 additions and 280 deletions

View File

@ -1,7 +1,8 @@
proxy更新日志: proxy更新日志:
v3.1 v3.1
1.优化了内网穿透功能,client只需要启动一个即可,server端启动的时候可以指定client端要暴露的端口。 1.优化了内网穿透功能,bridge,client和server只需要启动一个即可.
2. server端启动的时候可以指定client端要暴露的一个或者多个端口。
2.此次更新,tserver模式部分参数不兼容3.0。
v3.0 v3.0
1.此次更新不兼容2.x版本,重构了全部代码,架构更合理,利于功能模块的增加与维护。 1.此次更新不兼容2.x版本,重构了全部代码,架构更合理,利于功能模块的增加与维护。

View File

@ -22,7 +22,12 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp代理服务器,支
- 以前只能在局域网玩的,现在可以在任何地方玩. - 以前只能在局域网玩的,现在可以在任何地方玩.
- 替代圣剑内网通显IP内网通花生壳之类的工具. - 替代圣剑内网通显IP内网通花生壳之类的工具.
- ...   - ...  
### 手册目录
本页是最新v3.1手册,其他手册请点击下面链接查看.
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
### Fast Start ### Fast Start
提示:所有操作需要root权限. 提示:所有操作需要root权限.
**0.如果你的VPS是linux64位的系统,那么只需要执行下面一句,就可以完成自动安装和配置.** **0.如果你的VPS是linux64位的系统,那么只需要执行下面一句,就可以完成自动安装和配置.**
@ -45,7 +50,7 @@ wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_li
下载地址:https://github.com/snail007/goproxy/releases 下载地址:https://github.com/snail007/goproxy/releases
```shell ```shell
cd /root/proxy/ cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v2.0/proxy-linux-amd64.tar.gz wget https://github.com/snail007/goproxy/releases/download/v3.1/proxy-linux-amd64.tar.gz
``` ```
**3.下载自动安装脚本** **3.下载自动安装脚本**
```shell ```shell

View File

@ -78,8 +78,9 @@ func initConfig() (err error) {
tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool() tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String() tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
tunnelServerArgs.Remote = tunnelServer.Flag("remote", "client's network host:port").Short('r').Default("").String() //tunnelServerArgs.Remote = tunnelServer.Flag("remote", "client's network host:port").Short('R').Default("").String()
tunnelServerArgs.Local = tunnelServer.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() //tunnelServerArgs.Local = tunnelServer.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as :localip:localport@clienthost:clientport").Short('r').Default("").Strings()
//########tunnel-client######### //########tunnel-client#########
tunnelClient := app.Command("tclient", "proxy on tunnel client mode") tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
@ -104,6 +105,7 @@ func initConfig() (err error) {
tunnelBridgeArgs.Args = args tunnelBridgeArgs.Args = args
tunnelClientArgs.Args = args tunnelClientArgs.Args = args
tunnelServerArgs.Args = args tunnelServerArgs.Args = args
*tunnelServerArgs.Route = []string{}
poster() poster()
//regist services and run service //regist services and run service
@ -111,9 +113,10 @@ func initConfig() (err error) {
services.Regist("http", services.NewHTTP(), httpArgs) services.Regist("http", services.NewHTTP(), httpArgs)
services.Regist("tcp", services.NewTCP(), tcpArgs) services.Regist("tcp", services.NewTCP(), tcpArgs)
services.Regist("udp", services.NewUDP(), udpArgs) services.Regist("udp", services.NewUDP(), udpArgs)
services.Regist("tserver", services.NewTunnelServer(), tunnelServerArgs) services.Regist("tserver", services.NewTunnelServerManager(), tunnelServerArgs)
services.Regist("tclient", services.NewTunnelClient(), tunnelClientArgs) services.Regist("tclient", services.NewTunnelClient(), tunnelClientArgs)
services.Regist("tbridge", services.NewTunnelBridge(), tunnelBridgeArgs) services.Regist("tbridge", services.NewTunnelBridge(), tunnelBridgeArgs)
service, err = services.Run(serviceName) service, err = services.Run(serviceName)
if err != nil { if err != nil {
log.Fatalf("run service [%s] fail, ERR:%s", service, err) log.Fatalf("run service [%s] fail, ERR:%s", service, err)

View File

@ -6,7 +6,7 @@ fi
mkdir /tmp/proxy mkdir /tmp/proxy
cd /tmp/proxy cd /tmp/proxy
wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v3.0/proxy-linux-amd64.tar.gz wget https://github.com/snail007/goproxy/releases/download/v3.1/proxy-linux-amd64.tar.gz
# install monexec # install monexec
tar zxvf monexec_0.1.1_linux_amd64.tar.gz tar zxvf monexec_0.1.1_linux_amd64.tar.gz

View File

@ -25,6 +25,7 @@ type TunnelServerArgs struct {
Key *string Key *string
Remote *string Remote *string
Timeout *int Timeout *int
Route *[]string
} }
type TunnelClientArgs struct { type TunnelClientArgs struct {
Args Args

View File

@ -25,7 +25,7 @@ func Regist(name string, s Service, args interface{}) {
Name: name, Name: name,
} }
} }
func Run(name string) (service *ServiceItem, err error) { func Run(name string, args ...interface{}) (service *ServiceItem, err error) {
service, ok := servicesMap[name] service, ok := servicesMap[name]
if ok { if ok {
go func() { go func() {
@ -35,7 +35,11 @@ func Run(name string) (service *ServiceItem, err error) {
log.Fatalf("%s servcie crashed, ERR: %s\ntrace:%s", name, err, string(debug.Stack())) log.Fatalf("%s servcie crashed, ERR: %s\ntrace:%s", name, err, string(debug.Stack()))
} }
}() }()
err := service.S.Start(service.Args) if len(args) == 1 {
err = service.S.Start(args[0])
} else {
err = service.S.Start(service.Args)
}
if err != nil { if err != nil {
log.Fatalf("%s servcie fail, ERR: %s", name, err) log.Fatalf("%s servcie fail, ERR: %s", name, err)
} }

View File

@ -20,6 +20,44 @@ type TunnelServer struct {
sc utils.ServerChannel sc utils.ServerChannel
} }
type TunnelServerManager struct {
cfg TunnelServerArgs
udpChn chan UDPItem
sc utils.ServerChannel
}
func NewTunnelServerManager() Service {
return &TunnelServerManager{
cfg: TunnelServerArgs{},
udpChn: make(chan UDPItem, 50000),
}
}
func (s *TunnelServerManager) Start(args interface{}) (err error) {
s.cfg = args.(TunnelServerArgs)
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
}
for _, info := range *s.cfg.Route {
_routeInfo := strings.Split(info, "@")
server := NewTunnelServer()
local := _routeInfo[0]
remote := _routeInfo[1]
server.Start(TunnelServerArgs{
Args: s.cfg.Args,
Local: &local,
IsUDP: s.cfg.IsUDP,
Remote: &remote,
Key: s.cfg.Key,
Timeout: s.cfg.Timeout,
})
}
return
}
func (s *TunnelServerManager) Clean() {
}
func NewTunnelServer() Service { func NewTunnelServer() Service {
return &TunnelServer{ return &TunnelServer{
cfg: TunnelServerArgs{}, cfg: TunnelServerArgs{},
@ -37,11 +75,6 @@ func (s *TunnelServer) InitService() {
s.UDPConnDeamon() s.UDPConnDeamon()
} }
func (s *TunnelServer) Check() { func (s *TunnelServer) Check() {
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
}
if *s.cfg.Remote == "" { if *s.cfg.Remote == "" {
log.Fatalf("remote required") log.Fatalf("remote required")
} }
@ -122,7 +155,7 @@ func (s *TunnelServer) GetOutConn(id string) (outConn net.Conn, ID string, err e
} }
keyBytes := []byte(*s.cfg.Key) keyBytes := []byte(*s.cfg.Key)
keyLength := uint16(len(keyBytes)) keyLength := uint16(len(keyBytes))
ID = utils.NewUniqueID().String() ID = utils.Uniqueid()
IDBytes := []byte(ID) IDBytes := []byte(ID)
if id != "" { if id != "" {
ID = id ID = id

View File

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"math/rand"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -305,6 +306,11 @@ func ReadUDPPacket(_reader io.Reader) (srcAddr string, packet []byte, err error)
} }
return return
} }
func Uniqueid() string {
var src = rand.NewSource(time.Now().UnixNano())
s := fmt.Sprintf("%d", src.Int63())
return s[len(s)-5:len(s)-1] + fmt.Sprintf("%d", uint64(time.Now().UnixNano()))[8:]
}
// type sockaddr struct { // type sockaddr struct {
// family uint16 // family uint16

View File

@ -1,264 +0,0 @@
// Package xid is a globally unique id generator suited for web scale
//
// Xid is using Mongo Object ID algorithm to generate globally unique ids:
// https://docs.mongodb.org/manual/reference/object-id/
//
// - 4-byte value representing the seconds since the Unix epoch,
// - 3-byte machine identifier,
// - 2-byte process id, and
// - 3-byte counter, starting with a random value.
//
// The binary representation of the id is compatible with Mongo 12 bytes Object IDs.
// The string representation is using base32 hex (w/o padding) for better space efficiency
// when stored in that form (20 bytes). The hex variant of base32 is used to retain the
// sortable property of the id.
//
// Xid doesn't use base64 because case sensitivity and the 2 non alphanum chars may be an
// issue when transported as a string between various systems. Base36 wasn't retained either
// because 1/ it's not standard 2/ the resulting size is not predictable (not bit aligned)
// and 3/ it would not remain sortable. To validate a base32 `xid`, expect a 20 chars long,
// all lowercase sequence of `a` to `v` letters and `0` to `9` numbers (`[0-9a-v]{20}`).
//
// UUID is 16 bytes (128 bits), snowflake is 8 bytes (64 bits), xid stands in between
// with 12 bytes with a more compact string representation ready for the web and no
// required configuration or central generation server.
//
// Features:
//
// - Size: 12 bytes (96 bits), smaller than UUID, larger than snowflake
// - Base32 hex encoded by default (16 bytes storage when transported as printable string)
// - Non configured, you don't need set a unique machine and/or data center id
// - K-ordered
// - Embedded time with 1 second precision
// - Unicity guaranted for 16,777,216 (24 bits) unique ids per second and per host/process
//
// Best used with xlog's RequestIDHandler (https://godoc.org/github.com/rs/xlog#RequestIDHandler).
//
// References:
//
// - http://www.slideshare.net/davegardnerisme/unique-id-generation-in-distributed-systems
// - https://en.wikipedia.org/wiki/Universally_unique_identifier
// - https://blog.twitter.com/2010/announcing-snowflake
package utils
import (
"crypto/md5"
"crypto/rand"
"database/sql/driver"
"encoding/binary"
"errors"
"fmt"
"os"
"sync/atomic"
"time"
)
// Code inspired from mgo/bson ObjectId
// ID represents a unique request id
type ID [rawLen]byte
const (
encodedLen = 20 // string encoded len
decodedLen = 15 // len after base32 decoding with the padded data
rawLen = 12 // binary raw len
// encoding stores a custom version of the base32 encoding with lower case
// letters.
encoding = "0123456789abcdefghijklmnopqrstuv"
)
// ErrInvalidID is returned when trying to unmarshal an invalid ID
var ErrInvalidID = errors.New("xid: invalid ID")
// objectIDCounter is atomically incremented when generating a new ObjectId
// using NewObjectId() function. It's used as a counter part of an id.
// This id is initialized with a random value.
var objectIDCounter = randInt()
// machineId stores machine id generated once and used in subsequent calls
// to NewObjectId function.
var machineID = readMachineID()
// pid stores the current process id
var pid = os.Getpid()
// dec is the decoding map for base32 encoding
var dec [256]byte
func init() {
for i := 0; i < len(dec); i++ {
dec[i] = 0xFF
}
for i := 0; i < len(encoding); i++ {
dec[encoding[i]] = byte(i)
}
}
// readMachineId generates machine id and puts it into the machineId global
// variable. If this function fails to get the hostname, it will cause
// a runtime error.
func readMachineID() []byte {
id := make([]byte, 3)
if hostname, err := os.Hostname(); err == nil {
hw := md5.New()
hw.Write([]byte(hostname))
copy(id, hw.Sum(nil))
} else {
// Fallback to rand number if machine id can't be gathered
if _, randErr := rand.Reader.Read(id); randErr != nil {
panic(fmt.Errorf("xid: cannot get hostname nor generate a random number: %v; %v", err, randErr))
}
}
return id
}
// randInt generates a random uint32
func randInt() uint32 {
b := make([]byte, 3)
if _, err := rand.Reader.Read(b); err != nil {
panic(fmt.Errorf("xid: cannot generate random number: %v;", err))
}
return uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2])
}
// NewUniqueID generates a globaly unique ID
func NewUniqueID() ID {
var id ID
// Timestamp, 4 bytes, big endian
binary.BigEndian.PutUint32(id[:], uint32(time.Now().Unix()))
// Machine, first 3 bytes of md5(hostname)
id[4] = machineID[0]
id[5] = machineID[1]
id[6] = machineID[2]
// Pid, 2 bytes, specs don't specify endianness, but we use big endian.
id[7] = byte(pid >> 8)
id[8] = byte(pid)
// Increment, 3 bytes, big endian
i := atomic.AddUint32(&objectIDCounter, 1)
id[9] = byte(i >> 16)
id[10] = byte(i >> 8)
id[11] = byte(i)
return id
}
// FromString reads an ID from its string representation
func FromString(id string) (ID, error) {
i := &ID{}
err := i.UnmarshalText([]byte(id))
return *i, err
}
// String returns a base32 hex lowercased with no padding representation of the id (char set is 0-9, a-v).
func (id ID) String() string {
text := make([]byte, encodedLen)
encode(text, id[:])
return string(text)
}
// MarshalText implements encoding/text TextMarshaler interface
func (id ID) MarshalText() ([]byte, error) {
text := make([]byte, encodedLen)
encode(text, id[:])
return text, nil
}
// encode by unrolling the stdlib base32 algorithm + removing all safe checks
func encode(dst, id []byte) {
dst[0] = encoding[id[0]>>3]
dst[1] = encoding[(id[1]>>6)&0x1F|(id[0]<<2)&0x1F]
dst[2] = encoding[(id[1]>>1)&0x1F]
dst[3] = encoding[(id[2]>>4)&0x1F|(id[1]<<4)&0x1F]
dst[4] = encoding[id[3]>>7|(id[2]<<1)&0x1F]
dst[5] = encoding[(id[3]>>2)&0x1F]
dst[6] = encoding[id[4]>>5|(id[3]<<3)&0x1F]
dst[7] = encoding[id[4]&0x1F]
dst[8] = encoding[id[5]>>3]
dst[9] = encoding[(id[6]>>6)&0x1F|(id[5]<<2)&0x1F]
dst[10] = encoding[(id[6]>>1)&0x1F]
dst[11] = encoding[(id[7]>>4)&0x1F|(id[6]<<4)&0x1F]
dst[12] = encoding[id[8]>>7|(id[7]<<1)&0x1F]
dst[13] = encoding[(id[8]>>2)&0x1F]
dst[14] = encoding[(id[9]>>5)|(id[8]<<3)&0x1F]
dst[15] = encoding[id[9]&0x1F]
dst[16] = encoding[id[10]>>3]
dst[17] = encoding[(id[11]>>6)&0x1F|(id[10]<<2)&0x1F]
dst[18] = encoding[(id[11]>>1)&0x1F]
dst[19] = encoding[(id[11]<<4)&0x1F]
}
// UnmarshalText implements encoding/text TextUnmarshaler interface
func (id *ID) UnmarshalText(text []byte) error {
if len(text) != encodedLen {
return ErrInvalidID
}
for _, c := range text {
if dec[c] == 0xFF {
return ErrInvalidID
}
}
decode(id, text)
return nil
}
// decode by unrolling the stdlib base32 algorithm + removing all safe checks
func decode(id *ID, src []byte) {
id[0] = dec[src[0]]<<3 | dec[src[1]]>>2
id[1] = dec[src[1]]<<6 | dec[src[2]]<<1 | dec[src[3]]>>4
id[2] = dec[src[3]]<<4 | dec[src[4]]>>1
id[3] = dec[src[4]]<<7 | dec[src[5]]<<2 | dec[src[6]]>>3
id[4] = dec[src[6]]<<5 | dec[src[7]]
id[5] = dec[src[8]]<<3 | dec[src[9]]>>2
id[6] = dec[src[9]]<<6 | dec[src[10]]<<1 | dec[src[11]]>>4
id[7] = dec[src[11]]<<4 | dec[src[12]]>>1
id[8] = dec[src[12]]<<7 | dec[src[13]]<<2 | dec[src[14]]>>3
id[9] = dec[src[14]]<<5 | dec[src[15]]
id[10] = dec[src[16]]<<3 | dec[src[17]]>>2
id[11] = dec[src[17]]<<6 | dec[src[18]]<<1 | dec[src[19]]>>4
}
// Time returns the timestamp part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ID) Time() time.Time {
// First 4 bytes of ObjectId is 32-bit big-endian seconds from epoch.
secs := int64(binary.BigEndian.Uint32(id[0:4]))
return time.Unix(secs, 0)
}
// Machine returns the 3-byte machine id part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ID) Machine() []byte {
return id[4:7]
}
// Pid returns the process id part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ID) Pid() uint16 {
return binary.BigEndian.Uint16(id[7:9])
}
// Counter returns the incrementing value part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ID) Counter() int32 {
b := id[9:12]
// Counter is stored as big-endian 3-byte value
return int32(uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2]))
}
// Value implements the driver.Valuer interface.
func (id ID) Value() (driver.Value, error) {
b, err := id.MarshalText()
return string(b), err
}
// Scan implements the sql.Scanner interface.
func (id *ID) Scan(value interface{}) (err error) {
switch val := value.(type) {
case string:
return id.UnmarshalText([]byte(val))
case []byte:
return id.UnmarshalText(val)
default:
return fmt.Errorf("xid: scanning unsupported type: %T", value)
}
}