Example #1
0
// step3-4
func (s socks5Handler) readRequest() (string, bool) {
	var (
		buf            = make([]byte, 262) // 4+(1+255)+2
		host           string
		ofs            int
		ver, cmd, atyp byte
	)
	var msg = []byte{5, 0, 0, 1, 0, 0, 0, 0, 0, 0}
	setRTimeout(s.conn)
	_, err := s.conn.Read(buf)
	if err != nil {
		exception.Spawn(&err, "socks: read request")
		goto errLogging
	}
	ver, cmd, atyp = buf[0], buf[1], buf[3]
	if ver != S5_VER || cmd != 1 {
		exception.Spawn(&err, "socks: invalid request")
		goto errHandler
	}

	buf = buf[4:]
	switch atyp {
	case IPV4:
		host = net.IP(buf[:net.IPv4len]).String()
		ofs = net.IPv4len
	case IPV6:
		host = "[" + net.IP(buf[:net.IPv6len]).String() + "]"
		ofs = net.IPv6len
	case DOMAIN:
		dlen := int(buf[0])
		ofs = dlen + 1
		host = string(buf[1:ofs])
		// literal IPv6
		if strings.Count(host, ":") >= 2 && !strings.HasPrefix(host, "[") {
			host = "[" + host + "]"
		}
	default:
		exception.Spawn(&err, "socks: invalid request")
		goto errHandler
	}

	// accept
	_, err = s.conn.Write(msg)
	if err != nil {
		exception.Spawn(&err, "socks: write response")
		goto errLogging
	}

	host += ":" + strconv.Itoa(int(binary.BigEndian.Uint16(buf[ofs:])))
	return host, true

errHandler:
	msg[1] = 0x1 // general SOCKS server failure
	setWTimeout(s.conn)
	s.conn.Write(msg)
errLogging:
	log.Warningln(err)

	return NULL, false
}
Example #2
0
func (n *d5sman) authenticate(conn *Conn, session *Session) error {
	var err error
	setRTimeout(conn)
	hashSRand, err := ReadFullByLen(1, conn)
	if err != nil {
		// client aborted
		if IsClosedError(err) {
			return ABORTED_ERROR.Apply(err)
		} else {
			return exception.Spawn(&err, "srand: read connection")
		}
	}

	myHashSRand := hash256(n.sRand)
	if !bytes.Equal(hashSRand, myHashSRand) {
		// MITM ?
		return INCONSISTENT_HASH
	}

	// client identity
	setRTimeout(conn)
	idBuf, err := ReadFullByLen(1, conn)
	if err != nil {
		return exception.Spawn(&err, "auth: read connection")
	}

	user, passwd, err := n.deserializeIdentity(idBuf)
	if err != nil {
		return err
	}

	if log.V(log.LV_LOGIN) {
		log.Infoln("Login request:", user)
	}

	pass, err := n.AuthSys.Authenticate(user, passwd)
	if !pass {
		// authSys denied
		log.Warningf("Auth %s:%s failed: %v\n", user, passwd, err)
		// reply failed msg
		conn.Write([]byte{1, 0})
		return VALIDATION_FAILED
	}

	session.indentifySession(user, conn)
	w := newMsgWriter()
	w.WriteL1Msg([]byte{AUTH_PASS})
	w.WriteL2Msg(n.tunParams.serialize())
	// send tokens
	num := maxInt(GENERATE_TOKEN_NUM, n.Parallels+2)
	tokens := n.sessionMgr.createTokens(session, num)
	w.WriteL2Msg(tokens[1:]) // skip index=0

	setWTimeout(conn)
	err = w.WriteTo(conn)
	return exception.Spawn(&err, "setting: write connection")
}
Example #3
0
// finish DHE
// 1, dhPub, dhSign, rand
// 2, hashHello, version
func (n *d5sman) finishDHExchange(conn *Conn) (cf *CipherFactory, err error) {
	var dhPub, key []byte
	dhKey, _ := crypto.NewDHKey(DH_METHOD)

	setRTimeout(conn)
	dhPub, err = ReadFullByLen(2, conn)
	if err != nil {
		exception.Spawn(&err, "dh: read connection")
		return
	}

	w := newMsgWriter()
	myDhPub := dhKey.ExportPubKey()
	w.WriteL1Msg(myDhPub)

	myDhSign := DSASign(n.privateKey, myDhPub)
	w.WriteL1Msg(myDhSign)

	n.sRand = randMinArray()
	w.WriteL1Msg(n.sRand)

	setWTimeout(conn)
	err = w.WriteTo(conn)
	if err != nil {
		exception.Spawn(&err, "dh: write connection")
		return
	}

	key, err = dhKey.ComputeKey(dhPub)
	if err != nil {
		exception.Spawn(&err, "dh: compute")
		return
	}

	// setup cipher
	cf = NewCipherFactory(n.Cipher, key, n.dbcHello)
	conn.SetupCipher(cf, n.sRand)

	// encrypted
	w.WriteL1Msg(hash256(n.dbcHello))
	w.WriteL1Msg(ito4b(VERSION))

	setWTimeout(conn)
	err = w.WriteTo(conn)
	if err != nil {
		exception.Spawn(&err, "em: write connection")
		return
	}
	return
}
Example #4
0
// step1-2
func (s socks5Handler) handshake() bool {
	var buf = make([]byte, 2)
	var n, nmethods int
	var ver byte
	setRTimeout(s.conn)
	_, err := io.ReadFull(s.conn, buf)
	if err != nil {
		exception.Spawn(&err, "socks: read header")
		goto errLogging
	}

	ver, nmethods = buf[0], int(buf[1])
	if ver != S5_VER || nmethods < 1 {
		err = INVALID_SOCKS5_HEADER
		exception.Spawn(&err, "socks: read header [% x]", buf[:2])
		goto errHandler
	}

	buf = make([]byte, nmethods+1) // consider method non-00
	setRTimeout(s.conn)
	n, err = io.ReadAtLeast(s.conn, buf, nmethods)
	if err != nil || n != nmethods {
		err = INVALID_SOCKS5_HEADER
		exception.Spawn(&err, "socks: read header [% x]", buf)
		goto errHandler
	}

	// accept
	buf = []byte{5, 0}
	setWTimeout(s.conn)
	_, err = s.conn.Write(buf)
	if err == nil {
		return true
	} else {
		err = exception.Spawn(&err, "socks: write response")
		goto errLogging
	}

errHandler:
	// handshake error feedback
	// NO ACCEPTABLE METHODS
	buf = []byte{5, 0xff}
	setWTimeout(s.conn)
	s.conn.Write(buf)
errLogging:
	log.Warningln(err)
	return false
}
Example #5
0
// report hashRand0 then request authentication
// get tun params and tokens
func (n *d5cman) authThenFinishSetting(conn *Conn, t *tunParams) error {
	var err error
	w := newMsgWriter()
	// hash sRand
	w.WriteL1Msg(hash256(n.sRand))
	// identity
	w.WriteL1Msg(n.serializeIdentity())

	setWTimeout(conn)
	err = w.WriteTo(conn)
	if err != nil {
		return exception.Spawn(&err, "auth: write connection")
	}

	setRTimeout(conn)
	var buf, params []byte
	buf, err = ReadFullByLen(1, conn)
	if err != nil {
		return exception.Spawn(&err, "auth: read connection")
	}
	// auth_result
	switch buf[0] {
	case AUTH_PASS:
	default:
		return auth.AUTH_FAILED
	}

	// parse params
	params, err = ReadFullByLen(2, conn)
	if err != nil {
		return exception.Spawn(&err, "param: read connection")
	}
	t.deserialize(params)

	t.token, err = ReadFullByLen(2, conn)
	if err != nil {
		return exception.Spawn(&err, "token: read connection")
	}
	if len(t.token) < TKSZ || len(t.token)%TKSZ != 0 {
		return ILLEGAL_STATE.Apply("incorrect token")
	}
	if log.V(log.LV_TOKEN) {
		log.Infof("Received tokens size=%d\n", len(t.token)/TKSZ)
	}

	return nil
}
Example #6
0
// read dhPub from server and verify sign
// dhPubLen~1 | dhPub~? | signLen~1 | sign~? | rand
func (n *d5cman) finishDHExchange(conn *Conn) (cf *CipherFactory, err error) {
	var dhk, dhkSign []byte
	// recv: rhPub~2+256 or ecdhPub~2+32
	setRTimeout(conn)
	dhk, err = ReadFullByLen(1, conn)
	if err != nil {
		// maybe: closed conn or reset by peer error caused by dbcHello
		if IsClosedError(err) {
			return nil, ERR_TIME_ERROR.Apply(NULL)
		} else {
			exception.Spawn(&err, "dh: read response")
			return
		}
	}

	setRTimeout(conn)
	dhkSign, err = ReadFullByLen(1, conn)
	if err != nil {
		exception.Spawn(&err, "dh: read sign")
		return
	}

	if !DSAVerify(n.sPubKey, dhkSign, dhk) {
		// MITM ?
		return nil, VALIDATION_FAILED
	}

	key, err := n.dhKey.ComputeKey(dhk)
	if err != nil {
		exception.Spawn(&err, "dh: compute")
		return
	}

	n.sRand, err = ReadFullByLen(1, conn)
	if err != nil {
		exception.Spawn(&err, "srand: read connection")
		return
	}

	// setup cipher
	cf = NewCipherFactory(n.cipher, key, n.dbcHello)
	conn.SetupCipher(cf, n.sRand)
	return
}
Example #7
0
// verify encrypted message
// hashHello, version
func (n *d5cman) validate(conn *Conn) error {
	setRTimeout(conn)
	hashHello, err := ReadFullByLen(1, conn)
	if err != nil {
		return exception.Spawn(&err, "validate: read connection")
	}

	myHashHello := hash256(n.dbcHello)
	if !bytes.Equal(hashHello, myHashHello) {
		// MITM ?
		return INCONSISTENT_HASH
	}

	ver, err := ReadFullByLen(1, conn)
	if err != nil {
		return exception.Spawn(&err, "ver: read connection")
	}
	if err = compareVersion(ver); err != nil {
		return err
	}
	return nil
}
Example #8
0
func (n *d5cman) ResumeSession(p *tunParams, token []byte) (conn *Conn, err error) {
	var rawConn net.Conn
	rawConn, err = net.DialTimeout("tcp", n.sAddr, GENERAL_SO_TIMEOUT)
	if err != nil {
		exception.Spawn(&err, "resume: connnecting")
		return
	}
	conn = NewConn(rawConn, nullCipherKit)
	obf := makeDbcHello(TYPE_RES, preSharedKey(n.sPubKey))
	w := newMsgWriter()
	w.WriteMsg(obf)
	w.WriteMsg(token)

	err = w.WriteTo(conn)
	if err != nil {
		exception.Spawn(&err, "resume: write")
		return
	}

	conn.SetupCipher(p.cipherFactory, token)
	conn.SetId(n.provider, false)
	return conn, nil
}
Example #9
0
// 1-send dbcHello,dhPub
// dbcHello~256 | dhPubLen~2 | dhPub~?
func (n *d5cman) requestDHExchange(conn *Conn) (err error) {
	// obfuscated header
	obf := makeDbcHello(TYPE_NEW, preSharedKey(n.sPubKey))
	w := newMsgWriter().WriteMsg(obf)
	if len(obf) > DPH_P2 {
		n.dbcHello = obf[DPH_P2:]
	} else {
		n.dbcHello = obf
	}

	// dhke
	pub := n.dhKey.ExportPubKey()
	w.WriteL2Msg(pub)

	setWTimeout(conn)
	err = w.WriteTo(conn)
	exception.Spawn(&err, "dh: write connection")
	return
}