func (context *bootContext) startServer() { defer func() { ex.CatchException(advice(recover())) sigChan <- t.Bye }() conf, err := t.Parse_d5s_file(context.config) if err != nil { log.Fatalln(advice(err)) } context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Server is listening on", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKey, _ := c.NewDHKey(DH_METHOD) server := t.NewServer(conf, dhKey) context.components = append(context.components, server) context.closeable = append(context.closeable, ln) for { conn, err := ln.AcceptTCP() if err == nil { go server.TunnelServe(conn) } else { t.SafeClose(conn) } } }
func (context *bootContext) startServer() { defer func() { ex.CatchException(warning(recover())) sigChan <- t.Bye }() var conf = t.Parse_d5sFile(context.config) context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Server is listening on", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKeys := t.GenerateDHKeyPairs() server := t.NewServer(conf, dhKeys) context.statser = server for { conn, err := ln.AcceptTCP() if err == nil { go server.TunnelServe(conn) } else { t.SafeClose(conn) } } }
func (context *bootContext) startClient() { defer func() { ex.CatchException(warning(recover())) sigChan <- t.Bye }() var conf = t.Parse_d5cFile(context.config) context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Socks5/Http is working at", conf.ListenAddr) mgr := NewClientMgr(conf) context.statser = mgr ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() for { conn, err := ln.Accept() if err == nil { go mgr.selectClientServ(conn) } else { t.SafeClose(conn) } } }
// close for ending of queued task func (q *equeue) _close(force bool, close_code uint) { q.lock.Lock() defer q.lock.Unlock() e := q.edge if log.V(4) { switch close_code { case CLOSED_BY_ERR: log.Infoln("terminate", e.dest) case CLOSED_FORCE: log.Infoln("close", e.dest) case CLOSED_WRITE: log.Infof("closeW %s by peer\n", e.dest) } } for i, e := q.buffer.Len(), q.buffer.Front(); i > 0; i, e = i-1, e.Next() { f := e.Value.(*frame) if f != nil { f.free() } } q.buffer = nil if force { atomic.StoreUint32(&e.closed, TCP_CLOSED) SafeClose(e.conn) } else { closeW(e.conn) } }
func (nego *d5SNegotiation) verifyThenDHExchange(conn net.Conn, credBuf []byte) (key []byte) { userIdentity, err := RSADecrypt(credBuf, nego.RSAKeys.priv) ThrowErr(err) clientIdentity := string(userIdentity) if log.V(2) { log.Infoln("Auth clientIdentity:", SubstringBefore(clientIdentity, IDENTITY_SEP), "***") } allow, ex := nego.AuthSys.Authenticate(userIdentity) cDHPub, err := ReadFullByLen(2, conn) if !allow { // invalid user indentity log.Warningf("Auth %s failed: %v\n", clientIdentity, ex) conn.Write([]byte{0, 1, 0xff}) panic(ex) } nego.clientIdentity = clientIdentity key = takeSharedKey(nego.dhKeys, cDHPub) // if log.V(5) { // dumpHex("Sharedkey", key) // } buf := new(bytes.Buffer) buf.Write(nego.dhKeys.pubLen) buf.Write(nego.dhKeys.pub) _, err = buf.WriteTo(conn) return }
func (p *multiplexer) connectToDest(frm *frame, key string, tun *Conn) { defer func() { ex.CatchException(recover()) }() var ( dstConn net.Conn err error target = string(frm.data) ) dstConn, err = net.DialTimeout("tcp", target, GENERAL_SO_TIMEOUT) frm.length = 0 if err != nil { p.router.removePreRegistered(key) log.Errorf("Cannot connect to [%s] for %s error: %s\n", target, key, err) frm.action = FRAME_ACTION_OPEN_N tunWrite2(tun, frm) } else { if log.V(1) { log.Infoln("OPEN", target, "for", key) } dstConn.SetReadDeadline(ZERO_TIME) edge := p.router.register(key, target, tun, dstConn, false) // write edge frm.action = FRAME_ACTION_OPEN_Y if tunWrite2(tun, frm) == nil { p.relay(edge, tun, frm.sid) // read edge } else { // send open_y failed SafeClose(tun) } } }
func (s *Server) updateNow() { tc := calculateTimeCounter(true) // write atomically atomic.StorePointer(&s.tcPool, unsafe.Pointer(&tc)) if log.V(4) { log.Infoln("updateTimeCounterThread", len(tc)) } }
func NewGeoIPFilter(keyword string) (f *GeoIPFilter, e error) { if len(keyword) != 2 { return nil, fmt.Errorf("filter keyword must be 2-byte country_iso_code") } f = new(GeoIPFilter) f.keyword = StoU16(strings.ToUpper(keyword)) f.tab = deserialize(buildGeoDB()) if log.V(1) { log.Infoln("Init GeoIPFilter with target keyword", keyword) } return }
func (context *bootContext) startClient() { defer func() { ex.CatchException(advice(recover())) sigChan <- t.Bye }() conf, err := t.Parse_d5c_file(context.config) if err != nil { log.Fatalln(advice(err)) } context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Socks5/Http is working at", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKey, _ := c.NewDHKey(DH_METHOD) client := t.NewClient(conf, dhKey) context.components = append(context.components, client) context.closeable = append(context.closeable, ln) go client.StartTun(true) for { conn, err := ln.Accept() if err == nil { if client.IsReady() { go client.ClientServe(conn) continue } else { log.Errorf("No available tunnels for servicing new request") time.Sleep(time.Second) } } t.SafeClose(conn) } }
func (h *ConnPool) Select() *Conn { h.lock.Lock() defer h.lock.Unlock() if h.pool.Len() < 1 { return nil } sort.Sort(h.pool) if log.V(5) { log.Infoln("selected tun", h.pool[0].LocalAddr()) } selected := h.pool[0] atomic.AddInt64(&selected.priority.rank, -1) return selected }
// close for ending of queued task func (q *equeue) _close(force bool, close_code uint) { q.lock.Lock() defer q.lock.Unlock() e := q.edge if log.V(4) { switch close_code { case CLOSED_BY_ERR: log.Infoln("terminate", e.dest) case CLOSED_FORCE: log.Infoln("close", e.dest) case CLOSED_WRITE: log.Infof("closeW %s by peer\n", e.dest) } } q.buffer.Init() q.buffer = nil if force { atomic.StoreUint32(&e.closed, TCP_CLOSED) SafeClose(e.conn) } else { closeW(e.conn) } }
func (c *Client) initialNegotiation() (tun *Conn) { var tp = new(tunParams) var err error tun, err = c.nego.negotiate(tp) if err != nil { log.Errorf("Failed to connect %s, Retry after %s\n", c.nego.RemoteName(), RETRY_INTERVAL) return nil } c.token, c.tp = tp.token, tp tp.token = nil tun.identifier = c.nego.RemoteName() log.Infoln("Login to the gateway", c.nego.RemoteName(), "successfully") return tun }
func sendFrame(frm *frame) (werr bool) { dst := frm.conn.conn if log.V(5) { log.Infoln("SEND queue", frm) } dst.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT)) nw, ew := dst.Write(frm.data) if nw == int(frm.length) && ew == nil { return } werr = true // an error occured log.Warningf("Write edge(%s) error(%v). %s\n", frm.conn.dest, ew, frm) return }
func waitSignal() { USR2 := syscall.Signal(12) // fake signal-USR2 for windows signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, USR2) for sig := range sigChan { switch sig { case t.Bye: log.Exitln("Exiting.") return case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: log.Exitln("Terminated by", sig) return case USR2: context.doStats() default: log.Infoln("Ingore signal", sig) } } }
func (c *Client) initialNegotiation() (tun *Conn) { var tp = new(tunParams) var err error tun, err = c.nego.negotiate(tp) if err != nil { log.Errorf("Failed to connect %s, Retry after %s\n", c.nego.RemoteName(), RETRY_INTERVAL) if strings.Contains(err.Error(), "closed") { log.Warningln("Maybe your clock is inaccurate, or your client credential is invalid.") os.Exit(2) } return nil } c.token, c.tp = tp.token, tp tp.token = nil tun.identifier = c.nego.RemoteName() log.Infoln("Login to the gateway", c.nego.RemoteName(), "successfully") return tun }
func (n *dbcSerNego) verifyThenDHExchange(conn net.Conn) (key []byte) { // client identity segment setRTimeout(conn) credBuf, err := ReadFullByLen(2, conn) ThrowErr(err) user, passwd, err := n.idBlockDeserialize(credBuf) ThrowErr(err) if log.V(1) { log.Infoln("Auth client", user) } allow, err := n.AuthSys.Authenticate(user, passwd) if allow { n.clientIdentity = user } else { // client denied log.Warningf("Auth %s:%s failed: %v\n", user, passwd, err) // reply failed msg conn.Write([]byte{0, 1, AUTH_FAILED}) panic(err) } // read client RH-pub setRTimeout(conn) bobPub, err := ReadFullByLen(2, conn) ThrowErr(err) key, err = n.dhKey.ComputeKey(bobPub) ThrowErr(err) // send my RH-pub myPub := n.dhKey.ExportPubKey() buf := make([]byte, len(myPub)+2) binary.BigEndian.PutUint16(buf, uint16(len(myPub))) copy(buf[2:], myPub) setWTimeout(conn) _, err = conn.Write(buf) ThrowErr(err) return }
func (s *S5Step1) respondSocks5() bool { var ack = []byte{5, 0, 0, 1, 0, 0, 0, 0, 0, 0} if s.err != nil { // handshake error feedback if ex, y := s.err.(*exception.Exception); y { ack[1] = byte(ex.Code()) } else { ack[1] = 0x1 } s.conn.Write(ack) s.conn.Close() return true } // accept _, err := s.conn.Write(ack) if err != nil { log.Infoln(err) return true } return false }
func (p *multiplexer) connectToDest(frm *frame, key string, tun *Conn) { defer func() { ex.CatchException(recover()) }() var ( dstConn net.Conn err error target = string(frm.data) denied = false ) if p.filter != nil { denied = p.filter.Filter(target) } if !denied { dstConn, err = net.DialTimeout("tcp", target, GENERAL_SO_TIMEOUT) } if err != nil || denied { p.router.removePreRegistered(key) if denied { frm.action = FRAME_ACTION_OPEN_DENIED log.Warningf("Denied request [%s] for %s\n", target, key) } else { frm.action = FRAME_ACTION_OPEN_N log.Warningf("Cannot connect to [%s] for %s error: %s\n", target, key, err) } frameWriteHead(tun, frm) } else { edge := p.router.register(key, target, tun, dstConn, false) // write edge if log.V(1) { log.Infoln("OPEN", target, "for", key) } dstConn.SetReadDeadline(ZERO_TIME) frm.action = FRAME_ACTION_OPEN_Y if frameWriteHead(tun, frm) == nil { p.relay(edge, tun, frm.sid) // read edge } else { // send open_y failed SafeClose(tun) } } }
// TODO notify peer to slow down when queue increased too fast func (p *multiplexer) Listen(tun *Conn, handler event_handler, interval int) { tun.priority = &TSPriority{0, 1e9} p.pool.Push(tun) defer p.onTunDisconnected(tun, handler) tun.SetSockOpt(1, 0, 1) var ( header = make([]byte, FRAME_HEADER_LEN) idle = NewIdler(interval, p.isClient) router = p.router nr int er error frm *frame key string ) if !p.isClient { // server first ping client // make client aware of using a valid token. idle.ping(tun) } for { idle.newRound(tun) nr, er = io.ReadFull(tun, header) if nr == FRAME_HEADER_LEN { frm, er = parse_frame(header) if er == nil && len(frm.data) > 0 { // read All and discard tail random nr, er = io.ReadFull(tun, frm.data) frm.data = frm.data[:frm.length] } } if er != nil { // shutdown if atomic.LoadInt32(&p.status) < 0 { time.Sleep(time.Second) return } switch idle.consumeError(er) { case ERR_NEW_PING: if idle.ping(tun) == nil { continue } case ERR_PING_TIMEOUT: if log.V(1) { log.Errorln("Peer was unresponsive then close", tun.identifier) } default: if log.V(1) { log.Errorln("Error", tun.identifier, er) } } // abandon this connection return } key = sessionKey(tun, frm.sid) switch frm.action { case FRAME_ACTION_CLOSE_W: if edge, _ := router.getRegistered(key); edge != nil { edge.bitwiseCompareAndSet(TCP_CLOSE_W) edge.deliver(frm) } case FRAME_ACTION_CLOSE_R: if edge, _ := router.getRegistered(key); edge != nil { edge.bitwiseCompareAndSet(TCP_CLOSE_R) closeR(edge.conn) } case FRAME_ACTION_DATA: edge, pre := router.getRegistered(key) if edge != nil { edge.deliver(frm) } else if pre { router.preDeliver(key, frm) } else { if log.V(2) { log.Warningln("peer send data to an unexisted socket.", key, frm) } // trigger sending close to notice peer. pack(header, FRAME_ACTION_CLOSE_R, frm.sid, nil) if frameWriteBuffer(tun, header) != nil { return } } case FRAME_ACTION_OPEN: router.preRegister(key) go p.connectToDest(frm, key, tun) case FRAME_ACTION_OPEN_N, FRAME_ACTION_OPEN_Y, FRAME_ACTION_OPEN_DENIED: edge, _ := router.getRegistered(key) if edge != nil { if log.V(4) { log.Infoln(p.role, "recv OPEN_x", frm) } edge.ready <- frm.action close(edge.ready) } else { if log.V(2) { log.Warningln("peer send OPEN_x to an unexisted socket.", key, frm) } } case FRAME_ACTION_PING: if idle.pong(tun) == nil { atomic.AddInt32(&p.pingCnt, 1) } else { // reply pong failed return } case FRAME_ACTION_PONG: if idle.verify() { if p.isClient && idle.lastPing > 0 { sRtt, devRtt := idle.updateRtt() if DEBUG { log.Infof("sRtt=%d devRtt=%d", sRtt, devRtt) } if devRtt+(sRtt>>2) > sRtt { // restart ??? log.Warningf("Unstable network sRtt=%d devRtt=%d", sRtt, devRtt) } } } else { log.Warningln("Incorrect action_pong received") } case FRAME_ACTION_TOKENS: handler(evt_tokens, frm.data) default: log.Errorln(p.role, "Unrecognized", frm) } tun.Update() } }
// TODO notify peer to slow down when queue increased too fast func (p *multiplexer) Listen(tun *Conn, handler event_handler, interval int) { tun.priority = &TSPriority{0, 1e9} p.pool.Push(tun) defer p.onTunDisconnected(tun, handler) tun.SetSockOpt(1, 2, 1) var ( header = make([]byte, FRAME_HEADER_LEN) router = p.router idle = NewIdler(interval, p.isClient) nr int er error frm *frame key string ) if !p.isClient { // first ping frame will let client to be aware of using a valid token. idle.ping(tun) } for { idle.newRound(tun) nr, er = io.ReadFull(tun, header) if nr == FRAME_HEADER_LEN { frm = _parseFrameHeader(header) if frm.length > 0 { nr, er = io.ReadFull(tun, frm.data) } } if er != nil { switch idle.consumeError(er) { case ERR_NEW_PING: if idle.ping(tun) == nil { continue } case ERR_PING_TIMEOUT: if log.V(2) { log.Warningln("Peer was unresponsive then close", tun.identifier) } default: if log.V(2) { log.Warningln("Read tunnel", tun.identifier, er) } } return // error, abandon tunnel } key = sessionKey(tun, frm.sid) switch frm.action { case FRAME_ACTION_CLOSE_W: if edge, _ := router.getRegistered(key); edge != nil { edge.bitwiseCompareAndSet(TCP_CLOSE_W) edge.deliver(frm) } case FRAME_ACTION_CLOSE_R: if edge, _ := router.getRegistered(key); edge != nil { edge.bitwiseCompareAndSet(TCP_CLOSE_R) closeR(edge.conn) } case FRAME_ACTION_DATA: edge, pre := router.getRegistered(key) if edge != nil { edge.deliver(frm) } else if pre { router.preDeliver(key, frm) } else { if log.V(2) { log.Warningln("peer send data to an unexisted socket.", key, frm) } // trigger sending close to notice peer. _frame(header, FRAME_ACTION_CLOSE_R, frm.sid, nil) if tunWrite1(tun, header) != nil { return } } case FRAME_ACTION_OPEN: router.preRegister(key) go p.connectToDest(frm, key, tun) case FRAME_ACTION_OPEN_N, FRAME_ACTION_OPEN_Y: edge, _ := router.getRegistered(key) if edge != nil { if log.V(4) { if frm.action == FRAME_ACTION_OPEN_Y { log.Infoln(p.role, "recv OPEN_Y", frm) } else { log.Infoln(p.role, "recv OPEN_N", frm) } } edge.ready <- frm.action close(edge.ready) } else { if log.V(2) { log.Warningln("peer send OPENx to an unexisted socket.", key, frm) } } case FRAME_ACTION_PING: if idle.pong(tun) == nil { atomic.AddInt32(&p.pingCnt, 1) } else { // reply pong failed return } case FRAME_ACTION_PONG: if !idle.verify() { log.Warningln("Incorrect action_pong received") } case FRAME_ACTION_TOKENS: handler(evt_tokens, frm.data) default: log.Errorln(p.role, "Unrecognized", frm) } tun.Update() } }