Esempio n. 1
0
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
}
Esempio n. 2
0
func warning(e interface{}) interface{} {
	if err, y := e.(error); y {
		// 0.9.x to 0.10.x config error
		if strings.HasPrefix(err.Error(), "Unrecognized directives") {
			log.Warningf("Please read %s/wiki to learn more.", project_url)
		}
	}
	return e
}
Esempio n. 3
0
func (t *Session) tokensHandle(args []byte) {
	var cmd = args[0]
	switch cmd {
	case FRAME_ACTION_TOKEN_REQUEST:
		tokens := t.mgr.createTokens(t, GENERATE_TOKEN_NUM)
		tokens[0] = FRAME_ACTION_TOKEN_REPLY
		t.mux.bestSend(tokens, "replyTokens")
	default:
		log.Warningf("Unrecognized command=%x packet=[% x]\n", cmd, args)
	}
}
Esempio n. 4
0
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)
	}
	frm.length = 0
	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)
		}
		tunWrite2(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 tunWrite2(tun, frm) == nil {
			p.relay(edge, tun, frm.sid) // read edge
		} else { // send open_y failed
			SafeClose(tun)
		}
	}
}
Esempio n. 5
0
func tunWrite2(tun *Conn, frm *frame) (err error) {
	err = tun.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT * 2))
	if err != nil {
		return
	}
	var nr, nw int
	nr = int(frm.length) + FRAME_HEADER_LEN
	nw, err = tun.Write(frm.toNewBuffer())
	if nr != nw || err != nil {
		log.Warningf("Write tun(%s) error(%v) when sending %s\n", tun.sign(), err, frm)
		SafeClose(tun)
		return
	}
	return nil
}
Esempio n. 6
0
func tunWrite1(tun *Conn, buf []byte) (err error) {
	err = tun.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT * 2))
	if err != nil {
		return
	}
	var nr, nw int
	nr = len(buf)
	nw, err = tun.Write(buf)
	if nr != nw || err != nil {
		log.Warningf("Write tun(%s) error(%v) when sending buf.len=%d\n", tun.sign(), err, nr)
		SafeClose(tun)
		return
	}
	return nil
}
Esempio n. 7
0
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
}
Esempio n. 8
0
func (c *Client) saveTokens(data []byte) {
	var tokens []byte
	switch data[0] {
	case FRAME_ACTION_TOKEN_REQUEST:
		log.Warningf("unexpected token request")
		return
	case FRAME_ACTION_TOKEN_REPLY:
		tokens = data[1:]
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.token = append(c.token, tokens...)
	atomic.CompareAndSwapInt32(&c.State, CLT_PENDING, CLT_WORKING)
	c.pendingTK.notifyAll()
	if log.V(3) {
		log.Infof("Recv tokens=%d pool=%d\n", len(tokens)/TKSZ, len(c.token)/TKSZ)
	}
}
Esempio n. 9
0
func (c *Client) saveTokens(data []byte) {
	var tokens []byte
	switch data[0] {
	case FRAME_ACTION_TOKEN_REQUEST:
		log.Warningf("unexpected token request")
		return
	case FRAME_ACTION_TOKEN_REPLY:
		tokens = data[1:]
	}
	c.lock.Lock()
	c.token = append(c.token, tokens...)
	c.lock.Unlock()
	// wakeup waiting
	c.pendingTK.notifyAll()
	if log.V(3) {
		log.Infof("Recv tokens=%d pool=%d\n", len(tokens)/TKSZ, len(c.token)/TKSZ)
	}
}
Esempio n. 10
0
// frame writer
func frameWriteBuffer(tun *Conn, origin []byte) (err error) {
	// default timeout is 10s
	err = tun.SetWriteDeadline(time.Now().Add(WRITE_TUN_TIMEOUT))
	if err == nil {
		var nw int
		buf := frameTransform(origin)
		nw, err = tun.Write(buf)
		if nw != len(buf) || err != nil {
			idleLastR := time.Now().UnixNano() - tun.priority.last
			if IsTimeout(err) && idleLastR < int64(WRITE_TUN_TIMEOUT) {
				err = nil
			} else {
				log.Warningf("Write tun (%s) error (%v) buf.len=%d\n", tun.sign(), err, len(buf))
				SafeClose(tun)
			}
		}
	}
	return
}
Esempio n. 11
0
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
}
Esempio n. 12
0
func (n *dbcSerNego) negotiate(hConn *hashedConn, tcPool []uint64) (session *Session, err error) {
	var (
		nr  int
		buf = make([]byte, DP_P2I)
	)

	setRTimeout(hConn)
	nr, err = hConn.Read(buf)

	if nr == len(buf) {

		nr = 0 // reset nr
		ok, stype, len2 := verifyDbcHello(buf, n.sharedKey, tcPool)

		if ok {
			if len2 > 0 {
				setRTimeout(hConn)
				nr, err = io.ReadFull(hConn, buf[:len2])
			}

			if nr == int(len2) && err == nil {
				switch stype {
				case TYPE_NEW:
					return n.handshakeSession(hConn)
				case TYPE_DAT:
					return n.dataSession(hConn)
				}
			}
		}

	} // then may be a prober

	if err == nil {
		err = UNRECOGNIZED_REQ
	}

	// threats OR overlarge time error
	// We could use this log to block threats origin by external tools such as fail2ban.
	log.Warningf("Unrecognized Request from=%s len=%d\n", n.clientAddr, nr)
	return nil, err
}
Esempio n. 13
0
func (n *dbcCltNego) validateAndGetTokens(hConn *hashedConn, t *tunParams) {
	setRTimeout(hConn)
	buf, err := ReadFullByLen(2, hConn)
	ThrowErr(err)

	// compare version with remote
	myVer := VERSION
	rVer := binary.BigEndian.Uint32(buf)
	ofs := 4
	if rVer > myVer {
		rVerStr := fmt.Sprintf("%d.%d.%04d", rVer>>24, (rVer>>16)&0xFF, rVer&0xFFFF)
		myVer >>= 16
		rVer >>= 16
		if myVer == rVer {
			log.Warningf("Caution !!! Please upgrade to new version, remote is v%s\n", rVerStr)
		} else {
			ThrowErr(INCOMPATIBLE_VERSION.Apply(rVerStr))
			// return
		}
	}

	// check ibHash
	_ibHash := buf[ofs : ofs+20]
	ofs += 20
	if !bytes.Equal(n.ibHash, _ibHash) {
		// S->C is polluted.
		ThrowErr(INCONSISTENT_HASH.Apply("MitM attack"))
	}

	// parse params
	t.deserialize(buf, ofs)

	if log.V(3) {
		log.Infof("Received tokens size=%d\n", len(t.token)/TKSZ)
	}

	// validated or throws
	verifyHash(hConn, false)
}
Esempio n. 14
0
func (nego *d5CNegotiation) validateAndGetTokens(sconn *hashedConn, t *tunParams) {
	buf, err := ReadFullByLen(2, sconn)
	ThrowErr(err)
	tVer := VERSION
	oVer := binary.BigEndian.Uint32(buf)
	if oVer > tVer {
		oVerStr := fmt.Sprintf("%d.%d.%04d", oVer>>24, (oVer>>16)&0xFF, oVer&0xFFFF)
		tVer >>= 16
		oVer >>= 16
		if tVer == oVer {
			log.Warningf("Caution !!! Please upgrade to new version, remote is v%s\n", oVerStr)
		} else {
			err = INCOMPATIBLE_VERSION.Apply(oVerStr)
		}
		ThrowErr(err)
	}
	ofs := 4
	ofs += 2
	t.dtInterval = int(binary.BigEndian.Uint16(buf[ofs:]))
	ofs += 2
	t.tunQty = int(buf[ofs])
	t.token = buf[TUN_PARAMS_LEN:]
	if log.V(3) {
		n := len(buf) - TUN_PARAMS_LEN
		log.Infof("Received tokens count=%d\n", n/TKSZ)
	}
	rHash := sconn.RHashSum()
	wHash := sconn.WHashSum()
	_, err = sconn.Write(rHash)
	ThrowErr(err)
	oHash := make([]byte, TKSZ)
	_, err = sconn.Read(oHash)
	if !bytes.Equal(wHash, oHash) {
		log.Errorln("Server hash/r is inconsistence with the client/w")
		log.Errorf("rHash: [% x] wHash: [% x]\n", rHash, wHash)
		log.Errorf("oHash: [% x]\n", oHash)
		ThrowErr(INCONSISTENT_HASH)
	}
}
Esempio n. 15
0
func (nego *d5SNegotiation) negotiate(hConn *hashedConn) (session *Session, err error) {
	setSoTimeout(hConn)
	nego.clientAddr = hConn.RemoteAddr().String()
	var (
		nr  int
		buf = make([]byte, DMLEN1)
	)
	nr, err = hConn.Read(buf)
	if err != nil {
		return nil, err
	}

	if nr == DMLEN2 &&
		d5SumValid(buf[TKSZ-2], buf[TKSZ]) && d5SumValid(buf[TKSZ-1], buf[TKSZ+1]) {
		return nego.dataSession(hConn, buf)
	}
	if nr == DMLEN1 &&
		d5SumValid(buf[0xd5], buf[0xff]) {
		return nego.handshakeSession(hConn, buf)
	}
	log.Warningf("Unrecognized Request from=%s len=%d\n", nego.clientAddr, nr)
	return nil, NEGOTIATION_FAILED
}
Esempio n. 16
0
// 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()
	}
}