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) } } }
// 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 }
func (n *d5cman) Connect(p *tunParams) (conn *Conn, err error) { var rawConn net.Conn defer func() { n.dbcHello, n.sRand = nil, nil if exception.Catch(recover(), &err) { SafeClose(rawConn) if t, y := err.(*exception.Exception); y { // must terminate switch t.Origin { case ERR_TIME_ERROR: line := string(bytes.Repeat([]byte{'+'}, 30)) log.Warningln(line) log.Warningln("Maybe your clock is inaccurate, or your client credential is invalid.") log.Warningln(line) os.Exit(2) case INCOMPATIBLE_VERSION: log.Warningln(err) os.Exit(3) } } } }() rawConn, err = net.DialTimeout("tcp", n.sAddr, GENERAL_SO_TIMEOUT) n.dhKey, _ = crypto.NewDHKey(DH_METHOD) if err != nil { return } conn = NewConn(rawConn, nullCipherKit) if err = n.requestDHExchange(conn); err != nil { return } var cf *CipherFactory cf, err = n.finishDHExchange(conn) if err != nil { return } if err = n.validate(conn); err != nil { return } if err = n.authThenFinishSetting(conn, p); err != nil { return } p.cipherFactory = cf conn.SetId(n.provider, false) 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) } }