// TODO notify peer to slow down when queue increased too fast func (p *multiplexer) Listen(tun *Conn, handler event_handler, interval int) error { 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 nil } switch idle.consumeError(er) { case ERR_NEW_PING: if er = idle.ping(tun); er == nil { continue } case ERR_PING_TIMEOUT: er = ex.New("Peer was unresponsive then close") } // abandon this connection return er } // prefix tun.identifier 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(log.LV_WARN) { log.Warningln("Peer sent data to an unexisted socket.", key, frm) } // trigger sending close to notice peer. pack(header, FRAME_ACTION_CLOSE_R, frm.sid, nil) if er = frameWriteBuffer(tun, header); er != nil { return er } } case FRAME_ACTION_OPEN: router.preRegister(key) p.wg.Add(1) 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(log.LV_ACT_FRM) { log.Infoln(p.role, "received OPEN_x", frm) } edge.ready <- frm.action close(edge.ready) } else { if log.V(log.LV_WARN) { log.Warningln("Peer sent OPEN_x to an unexisted socket.", key, frm) } } case FRAME_ACTION_PING: if er = idle.pong(tun); er == nil { atomic.AddInt32(&p.pingCnt, 1) } else { // reply pong failed return er } case FRAME_ACTION_PONG: if idle.verify() { if p.isClient && idle.lastPing > 0 { sRtt, devRtt := idle.updateRtt() atomic.StoreInt32(&p.sRtt, sRtt) if DEBUG { log.Infof("sRtt=%d devRtt=%d", sRtt, devRtt) if devRtt+(sRtt>>2) > sRtt { // restart ??? log.Warningf("Network jitter sRtt=%d devRtt=%d", sRtt, devRtt) } } } } else { log.Warningln("Incorrect action_pong received") } case FRAME_ACTION_TOKENS: handler(evt_tokens, frm.data) default: // impossible return fmt.Errorf("Unrecognized %s", frm) } tun.Update() } }
"crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/asn1" "fmt" "io" "math/big" "strings" "github.com/Lafeng/deblocus/crypto" "github.com/Lafeng/deblocus/exception" ) var ( UNSUPPORTED_CIPHER = exception.New("Unsupported cipher") ) type cipherBuilder func(k, iv []byte) *XORCipherKit type cipherDesc struct { keyLen int ivLen int builder cipherBuilder } type cipherKit interface { encrypt(dst, src []byte) decrypt(dst, src []byte) Cleanup() }
ERR_NEW_PING = 0xf ERR_UNKNOWN = 0x0 ) const sid_max uint32 = 0xffff var ( // [1, 0xfffe] sid_seq uint32 bytePoolOnce sync.Once bytePool *bytepool.BytePool dialer *Dialer ) var ( ERR_TUN_NA = ex.New("No tunnels are available") ERR_DATA_TAMPERED = ex.New("data tampered") ) // -------------------- // event_handler // -------------------- type event byte const ( evt_tokens = event(1) ) type event_handler func(e event, msg ...interface{}) // --------------------
const ( PROT_UNKNOWN = 1 PROT_SOCKS5 = 2 PROT_HTTP = 3 PROT_HTTP_T = 4 PROT_LOCAL = 5 ) const ( HTTP_PROXY_STATUS_LINE = "HTTP/1.1 200 Connection established" CRLF = "\r\n" ) var ( // socks5 exceptions INVALID_SOCKS5_HEADER = exception.New("Invalid socks5 header") HOST_UNREACHABLE = exception.New("Host is unreachable") ) // socks5 protocol handler in client side // Ref: https://www.ietf.org/rfc/rfc1928.txt type socks5Handler struct { conn net.Conn } // step1-2 func (s socks5Handler) handshake() bool { var buf = make([]byte, 2) var n, nmethods int var ver byte setRTimeout(s.conn)
) const ( DT_PING_INTERVAL = 110 RETRY_INTERVAL = time.Second * 5 REST_INTERVAL = RETRY_INTERVAL ) const ( CLT_CLOSED int32 = -1 CLT_WORKING int32 = 0 CLT_PENDING int32 = 1 ) var ( ERR_REQ_TK_TIMEOUT = ex.New("Request token timeout") ERR_REQ_TK_ABORTED = ex.New("Requst token aborted") ) type Client struct { mux *multiplexer token []byte params *tunParams connInfo *connectionInfo lock sync.Locker dtCnt int32 reqCnt int32 state int32 round int32 pendingTK *timedWait }
CRLF = "\r\n" IDENTITY_SEP = "\x00" HTTP_PROXY_VER_LINE = "HTTP/1.1 200 Connection established" HTTP_PROXY_AGENT = "Proxy-Agent: " ) var ( // for main package injection VERSION uint32 VER_STRING string DEBUG bool ) var ( // socks5 exceptions INVALID_SOCKS5_HEADER = exception.New(0xff, "Invalid socks5 header") INVALID_SOCKS5_REQUEST = exception.New(0x07, "Invalid socks5 request") GENERAL_FAILURE = exception.New(0x01, "General failure") HOST_UNREACHABLE = exception.New(0x04, "Host is unreachable") ) var ( // D5 exceptions INVALID_D5PARAMS = exception.NewW("Invalid D5Params") D5SER_UNREACHABLE = exception.NewW("D5Server is unreachable") VALIDATION_FAILED = exception.NewW("Validation failed") NEGOTIATION_FAILED = exception.NewW("Negotiation failed") DATATUN_SESSION = exception.NewW("DT") INCONSISTENT_HASH = exception.NewW("Inconsistent hash") INCOMPATIBLE_VERSION = exception.NewW("Incompatible version") UNRECOGNIZED_REQ = exception.NewW("Unrecognized Request")
TIME_ERROR = 1 // minutes NULL = "" IDENTITY_SEP = "\x00" ) var ( // for main package injection VERSION uint32 VER_STRING string DEBUG bool ) var ( // D5 exceptions ILLEGAL_STATE = exception.New("Invalid State") VALIDATION_FAILED = exception.New("Validation Failed") INCONSISTENT_HASH = exception.New("Inconsistent Hashsum") INCOMPATIBLE_VERSION = exception.New("Incompatible Version") UNRECOGNIZED_REQ = exception.New("Unrecognized Request") ERR_TIME_ERROR = exception.New("Time Error") ABORTED_ERROR = exception.New("") ) // len_inByte enum: 1,2,4 func ReadFullByLen(len_inByte int, reader io.Reader) (buf []byte, err error) { lb := make([]byte, len_inByte) _, err = io.ReadFull(reader, lb) if err != nil { return }
CF_CLIENT = "deblocus.Client" CF_SERVER = "deblocus.Server" CF_URL = "URL" CF_KEY = "Key" CF_CRYPTO = "Crypto" CF_PRIVKEY = "PrivateKey" CF_CREDENTIAL = "Credential" CF_PAC = "PAC.Server" CF_FILE = "File" CONFIG_NAME = "deblocus.ini" SIZE_UNIT = "BKMG" ) var ( UNRECOGNIZED_SYMBOLS = exception.New("Unrecognized symbols") LOCAL_BIND_ERROR = exception.New("Local bind error") CONF_MISS = exception.New("Missed field in config:") CONF_ERROR = exception.New("Error field in config:") ) type ServerRole uint32 const ( SR_AUTO ServerRole = ^ServerRole(0) SR_CLIENT ServerRole = 0x0f SR_SERVER ServerRole = 0xf0 ) type ConfigMan struct { filepath string
package auth import ( "strings" "github.com/Lafeng/deblocus/exception" ) var ( NO_SUCH_USER = exception.New("No such user") AUTH_FAILED = exception.New("Auth failed") UNIMPLEMENTED_AUTHSYS = exception.New("Unimplemented authsys") INVALID_AUTH_CONF = exception.New("Invalid Auth config") INVALID_AUTH_PARAMS = exception.New("Invalid Auth params") ) type AuthSys interface { Authenticate(user, passwd string) (bool, error) AddUser(user *User) error UserInfo(user string) (*User, error) } type User struct { Name string Pass string } func GetAuthSysImpl(proto string) (AuthSys, error) { sep := strings.Index(proto, "://") if sep > 0 { switch proto[:sep] {
package crypto import ( "crypto/elliptic" "crypto/rand" "github.com/Lafeng/deblocus/exception" "github.com/monnand/dhkx" "math/big" "strings" ) var ( NoSuchDHMethod = exception.New(0, "No Such DH method") InvalidECCParam = exception.New(0, "Invalid ECC parameters") ) // enum: DHE, ECDHE-P224,256,384,521 func NewDHKey(name string) (DHKE, error) { name = strings.ToUpper(name) if name == "DHE" { return GenerateDHEKey() } if strings.HasPrefix(name, "ECDHE-") { name = name[6:] } var curve elliptic.Curve switch name { case "P224": curve = elliptic.P224() case "P256": curve = elliptic.P256()