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

This commit is contained in:
arraykeys@gmail.com
2017-09-25 18:55:12 +08:00
parent a99898729f
commit f985e24109
6 changed files with 64 additions and 579 deletions

View File

@ -21,7 +21,7 @@ func initConfig() (err error) {
//define args
tcpArgs := services.TCPArgs{}
httpArgs := services.HTTPArgs{}
// tlsArgs := services.TLSArgs{}
tunnelArgs := services.TunnelArgs{}
udpArgs := services.UDPArgs{}
//build srvice args
@ -56,6 +56,9 @@ func initConfig() (err error) {
udp := app.Command("udp", "proxy on udp mode")
udpArgs.Timeout = udp.Flag("timeout", "tcp timeout milliseconds when connect to parent proxy").Short('t').Default("2000").Int()
udpArgs.ParentType = udp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
//########tunnel#########
tunnel := app.Command("tcp", "proxy on tunnel mode")
tunnelArgs.Timeout = tunnel.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
kingpin.MustParse(app.Parse(os.Args[1:]))
@ -74,11 +77,13 @@ func initConfig() (err error) {
os.Exit(0)
}
}
poster()
//regist services and run service
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
services.Regist("http", services.NewHTTP(), httpArgs)
services.Regist("tcp", services.NewTCP(), tcpArgs)
services.Regist("udp", services.NewUDP(), udpArgs)
services.Regist("tunnel", services.NewTunnel(), tunnelArgs)
service, err = services.Run(serviceName)
if err != nil {
log.Fatalf("run service [%s] fail, ERR:%s", service, err)

572
main.go
View File

@ -9,111 +9,8 @@ import (
"syscall"
)
const APP_VERSION = "2.2"
const APP_VERSION = "3.0"
// var (
// checker Checker
// certBytes []byte
// keyBytes []byte
// outPool ConnPool
// basicAuth BasicAuth
// )
func init() {
// return
// //Init
// err = Init()
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// isLocalHTTP := cfg.GetBool("local-http")
// isTLS := cfg.GetBool("local-tls") || cfg.GetBool("parent-tls")
// isTCP := isLocalHTTP || isTLS || cfg.GetBool("local-tcp") || cfg.GetBool("parent-tcp")
// //InitTCP
// if isTCP {
// err = InitTCP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitTLS
// if isTLS {
// err = InitTLS()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitUDP
// if cfg.GetBool("local-udp") || cfg.GetBool("parent-udp") {
// err = InitUDP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitLocal
// err = InitLocal()
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitLocalTCP
// if cfg.GetBool("local-tcp") || cfg.GetBool("local-tls") || isLocalHTTP {
// err = InitLocalTCP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitLocalTLS
// if cfg.GetBool("local-tls") {
// err = InitLocalTLS()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitLocalHTTP
// if isLocalHTTP {
// err = InitLocalHTTP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitLocalUDP
// if cfg.GetBool("local-udp") {
// err = InitLocalUDP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitParent
// if cfg.GetString("parent") != "" {
// err = InitParent()
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitParentTCP
// if cfg.GetBool("parent-tcp") || cfg.GetBool("parent-tls") {
// err = InitParentTCP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitParentTLS
// if cfg.GetBool("parent-tls") {
// err = InitParentTLS()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// //InitParentUDP
// if cfg.GetBool("parent-udp") {
// err = InitParentUDP()
// }
// if err != nil {
// log.Fatalf("err : %s", err)
// }
// }
}
func main() {
err := initConfig()
if err != nil {
@ -122,7 +19,6 @@ func main() {
Clean(&service.S)
}
func Clean(s *services.Service) {
//block main()
signalChan := make(chan os.Signal, 1)
cleanupDone := make(chan bool)
signal.Notify(signalChan,
@ -140,469 +36,3 @@ func Clean(s *services.Service) {
}()
<-cleanupDone
}
// func Init() (err error) {
// return
// }
// func InitTCP() (err error) {
// return
// }
// func InitTLS() (err error) {
// certBytes, err = ioutil.ReadFile(cfg.GetString("cert"))
// if err != nil {
// log.Printf("err : %s", err)
// return
// }
// keyBytes, err = ioutil.ReadFile(cfg.GetString("key"))
// if err != nil {
// log.Printf("err : %s", err)
// return
// }
// return
// }
// func InitUDP() (err error) {
// return
// }
// func InitLocal() (err error) {
// return
// }
// func InitLocalTCP() (err error) {
// return
// }
// func InitLocalTLS() (err error) {
// return
// }
// func InitLocalHTTP() (err error) {
// err = InitBasicAuth()
// if err != nil {
// return
// }
// return
// }
// func InitLocalUDP() (err error) {
// return
// }
// func InitParent() (err error) {
// initOutPool(cfg.GetBool("parent-tls"), certBytes, keyBytes, cfg.GetString("parent"), cfg.GetInt("tcp-timeout"), cfg.GetInt("pool-size"), cfg.GetInt("pool-size")*2)
// checker = NewChecker(cfg.GetInt("check-timeout"), int64(cfg.GetInt("check-interval")), cfg.GetString("blocked"), cfg.GetString("direct"))
// log.Printf("use parent proxy : %s, udp : %v, tcp : %v, tls: %v", cfg.GetString("parent"), cfg.GetBool("parent-udp"), cfg.GetBool("parent-tcp"), cfg.GetBool("parent-tls"))
// return
// }
// func InitParentTCP() (err error) {
// return
// }
// func InitParentTLS() (err error) {
// return
// }
// func InitParentUDP() (err error) {
// return
// }
// func main() {
// //catch panic error
// defer func() {
// e := recover()
// if e != nil {
// log.Printf("err : %s,\ntrace:%s", e, string(debug.Stack()))
// }
// }()
// return
// sc := NewServerChannel(cfg.GetString("ip"), cfg.GetInt("port"))
// if cfg.GetBool("local-tls") {
// LocalTLSServer(&sc)
// } else if cfg.GetBool("local-tcp") {
// LocalTCPServer(&sc)
// } else if cfg.GetBool("local-udp") {
// LocalUDPServer(&sc)
// }
// log.Printf("proxy on %s , udp: %v, tcp: %v, tls: %v ,http: %v", (*sc.Listener).Addr(), cfg.GetBool("local-udp"), cfg.GetBool("local-tcp"), cfg.GetBool("local-tls"), cfg.GetBool("local-http"))
// clean()
// }
// func CheckTCPDeocder(inConn *net.Conn) (useProxy bool, address string, req *HTTPRequest, err error) {
// if cfg.GetBool("local-http") {
// useProxy, req, err = HTTPProxyDecoder(inConn)
// if err != nil {
// return
// }
// address = req.Host
// } else {
// address = cfg.GetString("parent")
// }
// if address == "" {
// useProxy = false
// } else if cfg.GetBool("always") {
// useProxy = true
// }
// return
// }
// func LocalTCPServer(sc *ServerChannel) {
// (*sc).ListenTCP(func(inConn net.Conn) {
// userProxy, address, req, err := CheckTCPDeocder(&inConn)
// if err != nil {
// if err != io.EOF {
// log.Printf("tcp decode error , ERR:%s", err)
// }
// return
// }
// TCPOutBridge(&inConn, userProxy, address, req)
// })
// }
// func LocalTLSServer(sc *ServerChannel) {
// (*sc).ListenTls(certBytes, keyBytes, func(inConn net.Conn) {
// userProxy, address, req, err := CheckTCPDeocder(&inConn)
// if err != nil {
// if err != io.EOF {
// log.Printf("tls decode error , ERR:%s", err)
// }
// return
// }
// TCPOutBridge(&inConn, userProxy, address, req)
// })
// }
// func LocalUDPServer(sc *ServerChannel) {
// (*sc).ListenUDP(func(packet []byte, localAddr, srcAddr *net.UDPAddr) {
// })
// }
// func TCPOutBridge(inConn *net.Conn, userProxy bool, address string, req *HTTPRequest) {
// var outConn net.Conn
// var _outConn interface{}
// var err error
// if userProxy {
// _outConn, err = outPool.Get()
// if err == nil {
// outConn = _outConn.(net.Conn)
// }
// } else {
// outConn, err = ConnectHost(address, cfg.GetInt("tcp-timeout"))
// }
// if err != nil {
// log.Printf("connect to %s , err:%s", address, err)
// closeConn(inConn)
// return
// }
// inAddr := (*inConn).RemoteAddr().String()
// outAddr := outConn.RemoteAddr().String()
// log.Printf("%s use proxy %v", address, userProxy)
// if req != nil {
// if req.IsHTTPS() && !userProxy {
// req.HTTPSReply()
// } else {
// outConn.Write(req.headBuf)
// }
// }
// IoBind(*inConn, outConn, func(err error) {
// log.Printf("conn %s - %s [%s] released", inAddr, outAddr, address)
// closeConn(inConn)
// closeConn(&outConn)
// }, func(n int, d bool) {}, 0)
// log.Printf("conn %s - %s [%s] connected", inAddr, outAddr, address)
// }
// func UDPOutBridge() {
// }
// func DoUDP() {
// if cfg.GetBool("local-udp") {
// } else {
// }
// }
// //DoTCP contains tcp && http
// func DoTCP() {
// //define command line args
// proxyIsTls = cfg.GetBool("parent-tls")
// localIsTls = cfg.GetBool("local-tls")
// proxyAddr = cfg.GetString("parent")
// bindIP := cfg.GetString("ip")
// bindPort := cfg.GetInt("port")
// timeout := cfg.GetInt("check-timeout")
// connTimeout = cfg.GetInt("tcp-timeout")
// interval := cfg.GetInt("check-interval")
// certFile := cfg.GetString("cert")
// keyFile := cfg.GetString("key")
// blockedFile := cfg.GetString("blocked")
// directFile := cfg.GetString("direct")
// isTCP = cfg.GetBool("tcp")
// poolInitSize := cfg.GetInt("pool-size")
// //check args required
// if proxyIsTls && proxyAddr == "" {
// log.Fatalf("parent proxy address required")
// }
// //check tls cert&key file
// if certFile == "" {
// certFile = "proxy.crt"
// }
// if keyFile == "" {
// keyFile = "proxy.key"
// }
// if proxyIsTls || localIsTls {
// certBytes, err = ioutil.ReadFile(certFile)
// if err != nil {
// log.Printf("err : %s", err)
// return
// }
// keyBytes, err = ioutil.ReadFile(keyFile)
// if err != nil {
// log.Printf("err : %s", err)
// return
// }
// }
// //init tls info string
// var proxyIsTlsStr string
// var localIsTlsStr string
// protocolStr := "tcp"
// if !isTCP {
// protocolStr = "http(s)"
// }
// if proxyIsTls {
// proxyIsTlsStr = "tls "
// }
// if localIsTls {
// localIsTlsStr = "tls "
// }
// //init checker and pool if needed
// if proxyAddr != "" {
// if !isTCP && !cfg.GetBool("always") {
// checker = NewChecker(timeout, int64(interval), blockedFile, directFile)
// }
// log.Printf("use %sparent %s proxy : %s", proxyIsTlsStr, protocolStr, proxyAddr)
// initOutPool(proxyIsTls, certBytes, keyBytes, proxyAddr, connTimeout, poolInitSize, poolInitSize*2)
// } else if isTCP {
// log.Printf("tcp proxy need parent")
// return
// }
// //init basic auth only in http mode
// if !isTCP {
// basicAuth = NewBasicAuth()
// if cfg.GetString("auth-file") != "" {
// httpAuthorization = true
// n, err := basicAuth.AddFromFile(cfg.GetString("auth-file"))
// if err != nil {
// log.Fatalf("auth-file:%s", err)
// }
// log.Printf("auth data added from file %d , total:%d", n, basicAuth.Total())
// }
// if len(cfg.GetStringSlice("auth")) > 0 {
// httpAuthorization = true
// n := basicAuth.Add(cfg.GetStringSlice("auth"))
// log.Printf("auth data added %d, total:%d", n, basicAuth.Total())
// }
// }
// //listen
// sc := NewServerChannel(bindIP, bindPort)
// var err error
// if localIsTls {
// err = sc.ListenTls(certBytes, keyBytes, connHandler)
// } else {
// err = sc.ListenTCP(connHandler)
// }
// //listen fail
// if err != nil {
// log.Fatalf("ERR:%s", err)
// } else {
// log.Printf("%s %sproxy on %s", protocolStr, localIsTlsStr, (*sc.Listener).Addr())
// }
// }
// func connHandler(inConn net.Conn) {
// defer func() {
// err := recover()
// if err != nil {
// log.Printf("connHandler crashed,err:%s\nstack:%s", err, string(debug.Stack()))
// closeConn(&inConn)
// }
// }()
// if isTCP {
// tcpHandler(&inConn)
// } else {
// httpHandler(&inConn)
// }
// }
// func tcpHandler(inConn *net.Conn) {
// var outConn net.Conn
// var _outConn interface{}
// _outConn, err = outPool.Get()
// if err != nil {
// log.Printf("connect to %s , err:%s", proxyAddr, err)
// closeConn(inConn)
// return
// }
// outConn = _outConn.(net.Conn)
// inAddr := (*inConn).RemoteAddr().String()
// outAddr := outConn.RemoteAddr().String()
// IoBind((*inConn), outConn, func(err error) {
// log.Printf("conn %s - %s released", inAddr, outAddr)
// closeConn(inConn)
// closeConn(&outConn)
// }, func(n int, d bool) {}, 0)
// log.Printf("conn %s - %s connected", inAddr, outAddr)
// }
// func httpHandler(inConn *net.Conn) {
// var b [4096]byte
// var n int
// n, err = (*inConn).Read(b[:])
// if err != nil {
// if err != io.EOF {
// log.Printf("read err:%s", err)
// }
// closeConn(inConn)
// return
// }
// var method, host, address string
// index := bytes.IndexByte(b[:], '\n')
// if index == -1 {
// log.Printf("data err:%s", string(b[:n])[:50])
// closeConn(inConn)
// return
// }
// fmt.Sscanf(string(b[:index]), "%s%s", &method, &host)
// if method == "" || host == "" {
// log.Printf("data err:%s", string(b[:n])[:50])
// closeConn(inConn)
// return
// }
// isHTTPS := method == "CONNECT"
// //http basic auth,only http
// if !isHTTPS {
// if httpAuthorization {
// //log.Printf("request :%s", string(b[:n]))
// authorization, err := getHeader("Authorization", b[:n])
// if err != nil {
// fmt.Fprint(*inConn, "HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"\"\r\n\r\nUnauthorized")
// closeConn(inConn)
// return
// }
// //log.Printf("Authorization:%s", authorization)
// basic := strings.Fields(authorization)
// if len(basic) != 2 {
// log.Printf("authorization data error,ERR:%s", authorization)
// closeConn(inConn)
// return
// }
// user, err := base64.StdEncoding.DecodeString(basic[1])
// if err != nil {
// log.Printf("authorization data parse error,ERR:%s", err)
// closeConn(inConn)
// return
// }
// authOk := basicAuth.Check(string(user))
// //log.Printf("auth %s,%v", string(user), authOk)
// if !authOk {
// fmt.Fprint(*inConn, "HTTP/1.1 401 Unauthorized\r\n\r\nUnauthorized")
// closeConn(inConn)
// return
// }
// }
// }
// var bytes []byte
// if isHTTPS { //https访问
// // [dd:dafds:fsd:dasd:2.2.23.3] or 2.2.23.3 or [dd:dafds:fsd:dasd:2.2.23.3]:2323 or 2.2.23.3:1234
// address = fixHost(host)
// if hostIsNoPort(host) { //host不带端口 默认443
// address = address + ":443"
// }
// } else { //http访问
// hostPortURL, err := url.Parse(host)
// if err != nil {
// log.Printf("url.Parse %s ERR:%s", host, err)
// closeConn(inConn)
// return
// }
// _host := fixHost(hostPortURL.Host)
// address = _host
// if hostIsNoPort(_host) { //host不带端口 默认80
// address = _host + ":80"
// }
// if _host != hostPortURL.Host {
// bytes = []byte(strings.Replace(string(b[:n]), hostPortURL.Host, _host, 1))
// host = strings.Replace(host, hostPortURL.Host, _host, 1)
// }
// }
// //get url , reslut host is the full url
// host, err = getURL(b[:n], host)
// // log.Printf("body:%s", string(b[:n]))
// // log.Printf("%s:%s", method, host)
// if err != nil {
// log.Printf("header data err:%s", err)
// closeConn(inConn)
// return
// }
// useProxy := false
// if proxyAddr != "" {
// if cfg.GetBool("always") {
// useProxy = true
// } else {
// if isHTTPS {
// checker.Add(address, true, method, "", nil)
// } else {
// if bytes != nil {
// checker.Add(address, false, method, host, bytes)
// } else {
// checker.Add(address, false, method, host, b[:n])
// }
// }
// useProxy, _, _ = checker.IsBlocked(address)
// }
// // var failN, successN uint
// // useProxy, failN, successN = checker.IsBlocked(address)
// //log.Printf("use proxy ? %s : %v ,fail:%d, success:%d", address, useProxy, failN, successN)
// //log.Printf("use proxy ? %s : %v", address, useProxy)
// }
// var outConn net.Conn
// var _outConn interface{}
// if useProxy {
// _outConn, err = outPool.Get()
// if err == nil {
// outConn = _outConn.(net.Conn)
// }
// } else {
// outConn, err = ConnectHost(address, connTimeout)
// }
// if err != nil {
// log.Printf("connect to %s , err:%s", address, err)
// closeConn(inConn)
// return
// }
// inAddr := (*inConn).RemoteAddr().String()
// outAddr := outConn.RemoteAddr().String()
// if isHTTPS {
// if useProxy {
// outConn.Write(b[:n])
// } else {
// fmt.Fprint(*inConn, "HTTP/1.1 200 Connection established\r\n\r\n")
// }
// } else {
// if bytes != nil {
// outConn.Write(bytes)
// } else {
// outConn.Write(b[:n])
// }
// }
// IoBind(*inConn, outConn, func(err error) {
// log.Printf("conn %s - %s [%s] released", inAddr, outAddr, address)
// closeConn(inConn)
// closeConn(&outConn)
// }, func(n int, d bool) {}, 0)
// log.Printf("conn %s - %s [%s] connected", inAddr, outAddr, address)
// }

View File

@ -18,6 +18,10 @@ type Args struct {
PoolSize *int
CheckParentInterval *int
}
type TunnelArgs struct {
Args
Timeout *int
}
type TCPArgs struct {
Args
Timeout *int

View File

@ -27,7 +27,9 @@ func NewHTTP() Service {
}
func (s *HTTP) InitService() {
s.InitBasicAuth()
if *s.cfg.Parent != "" {
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct)
}
}
func (s *HTTP) StopService() {
if s.outPool.Pool != nil {
@ -76,17 +78,18 @@ func (s *HTTP) callback(inConn net.Conn) {
return
}
address := req.Host
if req.IsHTTPS() {
s.checker.Add(address, true, req.Method, "", nil)
} else {
s.checker.Add(address, false, req.Method, req.URL, req.HeadBuf)
}
useProxy := true
if *s.cfg.Parent == "" {
useProxy = false
} else if *s.cfg.Always {
useProxy = true
} else {
if req.IsHTTPS() {
s.checker.Add(address, true, req.Method, "", nil)
} else {
s.checker.Add(address, false, req.Method, req.URL, req.HeadBuf)
}
//var n, m uint
useProxy, _, _ = s.checker.IsBlocked(req.Host)
//log.Printf("blocked ? : %v, %s , fail:%d ,success:%d", useProxy, address, n, m)

39
services/tunnel.go Normal file
View File

@ -0,0 +1,39 @@
package services
import "log"
type Tunnel struct {
cfg TunnelArgs
}
func NewTunnel() Service {
return &Tunnel{
cfg: TunnelArgs{},
}
}
func (s *Tunnel) InitService() {
}
func (s *Tunnel) Check() {
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
}
if s.cfg.CertBytes == nil || s.cfg.KeyBytes == nil {
log.Fatalf("cert and key file required")
}
}
func (s *Tunnel) StopService() {
}
func (s *Tunnel) Start(args interface{}) (err error) {
s.cfg = args.(TunnelArgs)
s.Check()
s.InitService()
return
}
func (s *Tunnel) Clean() {
s.StopService()
}

View File

@ -101,7 +101,11 @@ func (s *UDP) GetConn(connKey string) (conn net.Conn, isNew bool, err error) {
func (s *UDP) OutToTCP(packet []byte, localAddr, srcAddr *net.UDPAddr) (err error) {
numLocal := crc32.ChecksumIEEE([]byte(localAddr.String()))
numSrc := crc32.ChecksumIEEE([]byte(srcAddr.String()))
connKey := uint64((numLocal/10)*10 + numSrc%10)
mod := uint32(*s.cfg.PoolSize)
if mod == 0 {
mod = 10
}
connKey := uint64((numLocal/10)*10 + numSrc%mod)
conn, isNew, err := s.GetConn(fmt.Sprintf("%d", connKey))
if err != nil {
log.Printf("upd get conn to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)