github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/cmd/geph-client/listeners.go (about)

     1  package main
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net"
     6  	"net/http"
     7  	"time"
     8  
     9  	log "github.com/sirupsen/logrus"
    10  
    11  	"github.com/elazarl/goproxy"
    12  	"github.com/geph-official/geph2/cmd/geph-client/chinalist"
    13  	"github.com/geph-official/geph2/libs/cwl"
    14  	"github.com/geph-official/geph2/libs/tinysocks"
    15  	"golang.org/x/time/rate"
    16  )
    17  
    18  func listenStats() {
    19  	log.Infoln("STATS on", statsAddr)
    20  	// spin up stats server
    21  	statsMux := http.NewServeMux()
    22  	statsServ := &http.Server{
    23  		Addr:         statsAddr,
    24  		Handler:      statsMux,
    25  		ReadTimeout:  time.Minute,
    26  		WriteTimeout: time.Minute,
    27  	}
    28  	statsMux.HandleFunc("/proxy.pac", handleProxyPac)
    29  	statsMux.HandleFunc("/kill", handleKill)
    30  	statsMux.HandleFunc("/", handleStats)
    31  	statsMux.HandleFunc("/logs", handleLogs)
    32  	statsMux.HandleFunc("/debugpack", handleDebugPack)
    33  	statsMux.HandleFunc("/stacktrace", handleStacktrace)
    34  	err := statsServ.ListenAndServe()
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  }
    39  
    40  func listenHTTP() {
    41  	log.Infoln("HTTP on", httpAddr)
    42  	// HTTP proxy
    43  	srv := goproxy.NewProxyHttpServer()
    44  	srv.Tr = &http.Transport{
    45  		Dial: func(n, d string) (net.Conn, error) {
    46  			conn, err := dialTun(d)
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  			conn.(*net.TCPConn).SetKeepAlive(false)
    51  			conn.(*net.TCPConn).SetWriteBuffer(16384)
    52  			return conn, nil
    53  		},
    54  		IdleConnTimeout: time.Second * 60,
    55  		Proxy:           nil,
    56  	}
    57  	blankLogger := log.New()
    58  	blankLogger.SetOutput(ioutil.Discard)
    59  	srv.Logger = blankLogger
    60  	proxServ := &http.Server{
    61  		Addr:        httpAddr,
    62  		Handler:     srv,
    63  		ReadTimeout: time.Minute * 5,
    64  		IdleTimeout: time.Minute * 5,
    65  	}
    66  	err := proxServ.ListenAndServe()
    67  	if err != nil {
    68  		panic(err.Error())
    69  	}
    70  }
    71  
    72  func listenSocks() {
    73  	listener, err := net.Listen("tcp", socksAddr)
    74  	if err != nil {
    75  		panic(err)
    76  	}
    77  	semaphore := make(chan bool, 512)
    78  	downLimit := rate.NewLimiter(rate.Inf, 10000000)
    79  	upLimit := rate.NewLimiter(rate.Inf, 1000*1000)
    80  	useStats(func(sc *stats) {
    81  		if sc.Tier == "free" {
    82  			upLimit = rate.NewLimiter(100*1000, 1000*1000)
    83  		}
    84  	})
    85  	log.Infoln("SOCKS5 on", socksAddr)
    86  	for {
    87  		cl, err := listener.Accept()
    88  		if err != nil {
    89  			panic(err)
    90  		}
    91  		go func() {
    92  			defer cl.Close()
    93  			cl.(*net.TCPConn).SetKeepAlive(false)
    94  			select {
    95  			case semaphore <- true:
    96  				defer func() {
    97  					<-semaphore
    98  				}()
    99  			default:
   100  				return
   101  			}
   102  			cmd, rmAddrProt, err := tinysocks.ReadRequest(cl)
   103  			if err != nil {
   104  				log.Debugln("Bad SOCKS5 request:", err)
   105  				return
   106  			}
   107  			if cmd != tinysocks.CmdConnect {
   108  				log.Debugln("Unsupported command:", cmd)
   109  				tinysocks.CompleteRequestTCP(7, cl)
   110  				return
   111  			}
   112  			rmAddr := rmAddrProt.String()
   113  			host, port, err := net.SplitHostPort(rmAddr)
   114  			if realName := fakeIPToName(host); realName != "" {
   115  				rmAddr = net.JoinHostPort(realName, port)
   116  				host = realName
   117  			}
   118  			var remote net.Conn
   119  			var ok bool
   120  			if bypassHost(host) {
   121  				remote, err = net.Dial("tcp", rmAddr)
   122  				if err != nil {
   123  					log.Printf("[%v] failed to bypass %v", len(semaphore), remote)
   124  					tinysocks.CompleteRequestTCP(5, cl)
   125  					return
   126  				}
   127  				log.Debugf("[%v] BYPASSED %v", len(semaphore), rmAddr)
   128  				remote.(*net.TCPConn).SetKeepAlive(false) // app responsibility
   129  			} else {
   130  				start := time.Now()
   131  				var key interface{}
   132  				remote, key, ok = sWrap.DialCmd("proxy", rmAddr)
   133  				if !ok {
   134  					return
   135  				}
   136  				defer remote.Close()
   137  				incrCounter(key)
   138  				defer decrCounter(key)
   139  				ping := time.Since(start)
   140  				log.Debugf("[%v] opened %v in %vms through %v", len(semaphore), rmAddr, ping.Milliseconds(), remote.RemoteAddr())
   141  				useStats(func(sc *stats) {
   142  					pmil := ping.Milliseconds()
   143  					if time.Since(sc.PingTime).Seconds() > 30 || uint64(pmil) < sc.MinPing {
   144  						sc.MinPing = uint64(pmil)
   145  						sc.PingTime = time.Now()
   146  					}
   147  				})
   148  				if !ok {
   149  					tinysocks.CompleteRequestTCP(5, cl)
   150  					return
   151  				}
   152  			}
   153  			tinysocks.CompleteRequestTCP(0, cl)
   154  			go func() {
   155  				defer remote.Close()
   156  				defer cl.Close()
   157  				cwl.CopyWithLimit(remote, cl, upLimit, func(n int) {
   158  					useStats(func(sc *stats) {
   159  						sc.UpBytes += uint64(n)
   160  					})
   161  				}, time.Hour)
   162  			}()
   163  			cwl.CopyWithLimit(cl, remote,
   164  				downLimit, func(n int) {
   165  					useStats(func(sc *stats) {
   166  						sc.DownBytes += uint64(n)
   167  					})
   168  				}, time.Hour)
   169  		}()
   170  	}
   171  }
   172  
   173  // TODO bypass local domains
   174  func bypassHost(str string) bool {
   175  	return bypassChinese && chinalist.IsChinese(str)
   176  }