func proxhandler(w http.ResponseWriter, req *http.Request) { proxsemaph <- 0 defer func() { <-proxsemaph }() kilog.Debug("haha") xaxa := strings.Split(req.URL.Path, "/") if len(xaxa) != 3 { fmt.Println(xaxa) return } uniqid := xaxa[2] urlcache_lk.Lock() megaurl := urlcache[uniqid] fname := fnamecache[uniqid] urlcache_lk.Unlock() w.Header().Add("Content-Disposition", fmt.Sprintf("inline; filename=%s", fname)) kilog.Debug(megaurl) // Spin off megadl cmd := exec.Command("megadl", "--path", "-", megaurl) pipe, err := cmd.StdoutPipe() err = cmd.Start() if err != nil { kilog.Debug(err.Error()) return } go cmd.Wait() defer cmd.Process.Kill() io.Copy(w, pipe) }
func socksBeginConn(proxy *net.TCPAddr) (toret io.ReadWriteCloser, err error) { conn, err := net.DialTCP("tcp", nil, proxy) if err != nil { return } // Initial greeting: 0x05 0x01 0x00 (SOCKS5, 1 method, no authentication) _, err = conn.Write([]byte{0x05, 0x01, 0x00}) if err != nil { return } kilog.Debug("socks5: --> greeting") // Server should respond: 0x05 0x00 (SOCKS5, no auth selected) svresp := make([]byte, 2) _, err = io.ReadFull(conn, svresp) if err != nil || !(svresp[0] == 0x05 && svresp[1] == 0x00) { if err == nil { err = errors.New("socks5: server sent garbage") } return } kilog.Debug("socks5: <-- greeting") toret = conn return }
func (srv *Server) HandleClient(raw io.ReadWriteCloser) { defer raw.Close() /*raw, err := kiss.LLObfsServerHandshake(srv.prv.PublicKey(), raw) if err != nil { kilog.Debug("directory: client failed LLObfs handshake: %v", err.Error()) return }*/ var theirKey natrium.EdDSAPublic // "verifier" that copies down their public key copier := func(haha natrium.EdDSAPublic) bool { theirKey = haha return true } sock, err := kiss.KiSSNamedHandshake(srv.prv, copier, raw) if err != nil { kilog.Debug("directory: client failed KiSS handshake: %v", err.Error()) return } defer sock.Close() var request clntRequest err = struc.Unpack(sock, &request) if err != nil { kilog.Debug("directory: client sent malformed request: %v", err.Error()) return } //fmt.Println(request) srv.rqDispatch(sock, request) }
func addtocache(w http.ResponseWriter, req *http.Request) { err := req.ParseForm() if err != nil { return } megaurl := req.Form.Get("megaurl") kilog.Debug(megaurl) uniqid := make([]byte, 16) rand.Read(uniqid) xaxa := make([]byte, 100) base32.StdEncoding.Encode(xaxa, uniqid) id := strings.Replace(strings.ToLower(string(xaxa[:base32.StdEncoding.EncodedLen(16)])), "=", "", -1) kilog.Debug(id) urlcache_lk.Lock() urlcache[id] = megaurl fnamecache[id] = req.Form.Get("filename") urlcache_lk.Unlock() fmt.Fprintf(w, ` <!DOCTYPE html> <html> <head> <title>megaproxy</title> </head> <body> Your <a href="dl/%s">proxied URL</a> </body> </html>`, id) }
func tcpLoop() { listener, err := net.ListenTCP("tcp", transThis) if err != nil { kilog.Critical("%v", err.Error()) os.Exit(-1) } for { clnt, err := listener.AcceptTCP() if err != nil { kilog.Critical("%v", err.Error()) os.Exit(-1) } go func() { defer clnt.Close() defer clnt.CloseRead() defer clnt.CloseWrite() lol, err := clnt.File() if err != nil { panic(err.Error()) } haha := C.getdestaddr_iptables(C.int(lol.Fd())) lol.Close() sdf := make([]byte, 4) binary.LittleEndian.PutUint32(sdf, uint32(haha.sin_addr.s_addr)) port := binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&haha.sin_port))[:]) rmAddr := &net.TCPAddr{sdf, int(port), ""} dnsLock.Lock() rmName, ok := ipToName[rmAddr.IP.String()] dnsLock.Unlock() var rmConn io.ReadWriteCloser // see if we should connect IP or name if !ok { kilog.Warning("unmapped IP received (%v), misconfig?", rmAddr) rmConn, err = socksConnectIP(socksNext, rmAddr) } else { kilog.Debug("mapped IP received (%v -> %v)", rmAddr, rmName) rmConn, err = socksConnectName(socksNext, rmName, rmAddr.Port) } if err != nil { kilog.Debug("%v", err) return } defer rmConn.Close() go func() { defer rmConn.Close() defer clnt.Close() defer clnt.CloseRead() defer clnt.CloseWrite() io.Copy(rmConn, clnt) }() io.Copy(clnt, rmConn) kilog.Debug("closing client") }() } }
// DNS requests go to this function func dnsHandle(w dns.ResponseWriter, r *dns.Msg) { name := r.Question[0].Name if !namePattern.MatchString(name) { kilog.Debug("%v does not match pattern, forwarding", name) dnsForward(w, r) return } // otherwise kilog.Debug("%v matches pattern, handling", name) dnsLock.Lock() defer dnsLock.Unlock() // check in table first fakeIP, ok := nameToIP[name] if !ok { // place in table var nwIP string for { haha := ipAlloc().String() _, exists := ipToName[haha] if exists { continue } nwIP = haha break } fakeIP = nwIP nameToIP[name] = fakeIP ipToName[fakeIP] = name // remove in 30 minutes go func() { time.Sleep(time.Minute * 30) dnsLock.Lock() defer dnsLock.Unlock() delete(nameToIP, name) delete(ipToName, fakeIP) }() } // return the fake IP to the user resp := new(dns.A) resp.Hdr.Name = name resp.Hdr.Ttl = 1 // very short resp.Hdr.Class = dns.ClassINET resp.Hdr.Rrtype = dns.TypeA resp.A = net.ParseIP(fakeIP) towrite := new(dns.Msg) towrite.Id = r.Id towrite.RecursionAvailable = true towrite.RecursionDesired = true towrite.Response = true towrite.Question = r.Question towrite.Answer = make([]dns.RR, 1) towrite.Answer[0] = resp w.WriteMsg(towrite) kilog.Debug("returning mapping %v -> %v", name, fakeIP) }
func (ns *NodeState) do_AMB_REGISTER(sok io.ReadWriteCloser, req textprot.TextReq) (err error) { if len(req.Args) == 0 { err = errors.New("core2core: server got truncated AMB_REGISTER") return } bts, err := hex.DecodeString(req.Args[0]) if err != nil { return err } var kee [32]byte copy(kee[:], bts) fmt.Printf("%x\n", kee[:]) // unlock once the kiricom state is in place ns.Lock() _, ok := ns.ambState[kee] if ok { ns.Unlock() err = (&textprot.TextReq{ Verb: "NOPE", }).WriteTo(sok) return } dieInDisgrace := func() { ns.Lock() delete(ns.ambState, kee) ns.Unlock() } defer kilog.Debug("core2core: ambassador register for %x terminated", kee[:]) // signal OKAY err = (&textprot.TextReq{ Verb: "OKAY", }).WriteTo(sok) if err != nil { kilog.Debug("core2core: WHAT %v", err.Error()) dieInDisgrace() return } // construct the client kiricom state kcstat := kiricom.NewClientCtx(8192, sok) ns.ambState[kee] = kcstat ns.Unlock() defer dieInDisgrace() defer kcstat.Close() kcstat.WaitDeath() return }
func BuildCircuit(slc []dirclient.KNode, subchannel int) (io.ReadWriteCloser, error) { // this returns a checker whether a public key is valid pubkey_checker := func(hsh string) func([]byte) bool { return func([]byte) bool { return true } return func(xaxa []byte) bool { hashed := hash_base32(xaxa) return subtle.ConstantTimeCompare([]byte(hashed), []byte(hsh)) == 1 } } // circuit-building loop gwire, err := dialer.Dial(Old2New(slc[0].Address)) if err != nil { return nil, err } wire, err := kiss.TransportHandshake(kiss.GenerateDHKeys(), gwire, pubkey_checker(slc[0].PublicKey)) if err != nil { gwire.Close() return nil, err } for _, ele := range slc[1:] { kilog.Debug("Connecting to node %v...", string([]byte(ele.PublicKey)[:10])) // extend wire _, err = wire.Write(append([]byte{byte(len(ele.PublicKey))}, ele.PublicKey...)) if err != nil { gwire.Close() return nil, err } verifier := pubkey_checker(ele.PublicKey) // at this point wire is raw (well unobfs) connection to next wire, err = kiss.TransportHandshake(kiss.GenerateDHKeys(), wire, verifier) if err != nil { kilog.Debug("Died when transport at %s", ele.PublicKey) gwire.Close() return nil, err } kilog.Debug("Connected to node %v!", string([]byte(ele.PublicKey)[:10])) } _, err = wire.Write([]byte{byte(subchannel)}) if err != nil { gwire.Close() return nil, err } kilog.Debug("Opened subchannel %d", subchannel) return wire, nil }
func make_icom_ctx(underlying io.ReadWriteCloser, is_server bool, do_junk bool, PAUSELIM int) *icom_ctx { ctx := new(icom_ctx) ctx.is_dead = false ctx.underlying = underlying ctx.our_srv = VSListen() ctx.write_ch = make(chan icom_msg) // Killswitch is closed when the entire ctx should be abandoned. killswitch := make(chan bool) ctx.killswitch = killswitch var _ks_exec sync.Once KILL := func() { _ks_exec.Do(func() { kilog.Debug("Killswitching!") ctx.underlying.Close() ctx.is_dead = true close(killswitch) close(ctx.our_srv.vs_ch) }) } // Run the main thing go run_icom_ctx(ctx, KILL, is_server, do_junk, PAUSELIM) return ctx }
func HandleServer(conn io.ReadWriteCloser) { defer conn.Close() // Read 1 byte command + 40 bytes key line := make([]byte, 41) _, err := io.ReadFull(conn, line) if err != nil { return } // Switch on command switch line[0] { case 0x00: // This is an upload // We get contents first buff := new(bytes.Buffer) _, err := io.Copy(buff, conn) if err != nil { kilog.Debug("DHT: Client died while uploading value: %s", err.Error()) return } key := dhtkey(kiss.KeyedHash(buff.Bytes(), hashConst) } }
func socksConnectIP(proxy *net.TCPAddr, remote *net.TCPAddr) (toret io.ReadWriteCloser, err error) { conn, err := socksBeginConn(proxy) if err != nil { return } // Connection request // 0x05 0x01 0x00 0x01 0x## 0x## 0x## 0x## 0x$$ 0x$$ // VERS TCP RESV IPv4 IP01 IP02 IP03 IP04 PT01 PT02 req := []byte{0x05, 0x01, 0x00, 0x01, remote.IP[0], remote.IP[1], remote.IP[2], remote.IP[3], byte(remote.Port / 256), byte(remote.Port % 256)} _, err = conn.Write(req) if err != nil { return } kilog.Debug("socks5: --> IP connection request (%v)", remote.IP) // Server response // 0x05 0x%% 0x00 0x01 0x## 0x## 0x## 0x## 0x$$ 0x$$ // VERS RESP RESV ... resp := make([]byte, 10) _, err = io.ReadFull(conn, resp) if err != nil { return } return socksParseResponse(resp, conn) }
func (sg *servGroup) connAmb(i int) (*kiricom.ServerCtx, error) { nonce := make([]byte, 8) binary.BigEndian.PutUint64(nonce, uint64(i)) hash := natrium.SecureHash(sg.aidee.PublicKey(), nonce) kilog.Debug("serv: building circuit %v -> %x for %v", i, hash, sg.aidee.PublicKey()) var tgt directory.ChordKey tgt.FromBytes(hash) // build circuit to each and every one of them thingy, err := buildCirc(tgt) if err != nil { //thingy.Destroy() return nil, err } haha, err := thingy.RegAmbassador(sg.aidee.PublicKey()) if err != nil { thingy.Destroy() if err == core2core.ErrRejectedReq { kilog.Warning("serv: circuit number %v for %v rejected", i, sg.aidee.PublicKey()) return nil, err } else { return nil, err } } return haha, nil }
func (cc *commonCtx) destroy(msg error) { cc.once.Do(func() { close(cc.deadch) go cc.carrier.Close() cc.err = msg kilog.Debug("kiricom: commonCtx dying due to %v", msg.Error()) }) }
func (sg *servGroup) runAmbass(i int, ctx *kiricom.ServerCtx) { for { client, err := ctx.Accept() if err != nil { kilog.Debug("serv: ambassador %v for %v dying due to %v, trying to resurrect", i, sg.aidee.PublicKey(), err.Error()) go sg.revAmbass(i) return } select { case sg.wirech <- client: kilog.Debug("serv: %v accepted a client from circuit %v", sg.aidee.PublicKey(), i) case <-sg.deadch: kilog.Debug("serv: %v closing circuit %v gracefully", sg.aidee.PublicKey(), i) return } } }
func RunMultiplexSOCKSServer(transport io.ReadWriteCloser) { ctx := make_icom_ctx(transport, true, false, 2048) for { thing, err := ctx.our_srv.Accept() if err != nil { return } go func() { defer thing.Close() addr, err := socks5.ReadRequest(thing) if err != nil { return } remote, err := net.DialTimeout("tcp", addr, time.Second*20) if err != nil { kilog.Debug("Connection to %s failed: %s", addr, err.Error()) e := err.(net.Error) if e.Timeout() { socks5.CompleteRequest(0x06, thing) } else { socks5.CompleteRequest(0x01, thing) } return } defer remote.Close() rlrem := remote err = socks5.CompleteRequest(0x00, thing) if err != nil { return } go func() { defer rlrem.Close() io.Copy(rlrem, thing) }() kilog.Debug("Opened connection to %s", addr) io.Copy(thing, rlrem) }() } }
func sc_server_handler(_wire net.Conn) (err error) { defer func() { if err != nil { kilog.Debug("sc_server_handler returning err=%s", err.Error()) } }() defer _wire.Close() wire, err := kiss.Obfs3fHandshake(_wire, true) if err != nil { //kilog.Debug(err.Error()) return nil } return sc_server_real_handler(wire) }
func (cc *commonCtx) thrWatchdog() { for { select { case <-time.After(time.Second * 120): cc.destroy(errors.New("timeout")) return case <-cc.deadch: return case <-cc.wdch: // watchdog is kicked, redo kilog.Debug("kiricom: watchdog kicked") } } }
func (ctx *stew_ctx) run_stew(is_server bool) { defer func() { if x := recover(); x != nil { kilog.Debug("%v", x) } }() for { select { case <-ctx.killswitch: kilog.Debug("KILLSWITCH signalled for stew layer!") return case thing := <-ctx.llctx.ordered_ch: //kilog.Debug("Received thing with ctr=%d (%v)", thing.seqnum, is_server) pkt := bytes_to_stew_message(thing.payload) if pkt.category == m_open && is_server { remote_addr := string(pkt.payload) desired_connid := pkt.connid ctx.lock.Lock() ctx.conntable[desired_connid] = make(chan stew_message, 256) ctx.lock.Unlock() go ctx.attacht_remote(remote_addr, desired_connid) } else if pkt.category == m_close || pkt.category == m_data || pkt.category == m_more { ctx.lock.RLock() ch := ctx.conntable[pkt.connid] ctx.lock.RUnlock() if ch == nil { //kilog.Debug("stew_message with illegal connid received, killing connid") continue } ch <- pkt } else if pkt.category == m_dns { // not implemented } else { } } } }
func socksConnectName(proxy *net.TCPAddr, remote string, port int) (toret io.ReadWriteCloser, err error) { conn, err := socksBeginConn(proxy) if err != nil { return } if len(remote) >= 256 { err = errors.New("socks5: name too long") return } //remote = "google.com" // TODO REMOVE //port = 80 // Connection request // 0x05 0x01 0x00 0x03 0x$$ ..... // VERS TCP RESV DNS LEN ..... req := []byte{0x05, 0x01, 0x00, 0x03, byte(len(remote))} req = append(req, []byte(remote)...) req = append(req, []byte{byte(port / 256), byte(port % 256)}...) _, err = conn.Write(req) if err != nil { return } kilog.Debug("socks5: --> name connection request (%v)", remote) // Read response back resp := []byte{0, 0, 0, 0, 0} // same length, convenience _, err = io.ReadFull(conn, resp) if err != nil { return } kilog.Debug("socks5: <-- final response hdr (len = %v)", resp[4]) io.ReadFull(conn, make([]byte, resp[4]+5)) kilog.Debug("socks5: <-- final response bdy") return socksParseResponse(resp, conn) }
func (ctx *stew_ctx) attacht_remote(remote_addr string, connid int) { remconn, err := net.Dial("tcp", remote_addr) if err != nil { kilog.Debug("attacht_remote failed to connect to %d!", remote_addr) return } xaxa := (remconn).(*net.TCPConn) xaxa.SetLinger(0) xaxa.SetNoDelay(true) defer xaxa.Close() tunnel_connection(ctx, connid, xaxa) }
func initialize() { kilog.Info("SAGIRI version %v initializing...", VERSION) flag.Parse() lol, err := getPublicIP() kilog.Info("%v %v", lol, err) if isDirectory { runDir() os.Exit(0) } switch dirHelper { case "internal": dirProvider = directory.DefaultProvider("sanctum.sagiri.niwl.io:2378") } // obtain directory info id := directory.NewClient(natrium.EdDSAGenerateKey()) kilog.Debug("master key: %v", id.GetPrivate().PublicKey()) getNeighs(id) go func() { for { time.Sleep(time.Minute) getNeighs(id) } }() // set up core node if onionPort != 0 { ip, err := getPublicIP() if err != nil { panic(err.Error()) } id.SetAddress(&net.TCPAddr{IP: ip, Port: onionPort, Zone: "tcp"}) dirClient = id go runCore(id) } else { dirClient = id startSocks() startControl() go func() { log.Println(http.ListenAndServe("0.0.0.0:6060", nil)) }() } kilog.Info("SAGIRI finished initializing.") }
func make_stew_ctx() *stew_ctx { toret := new(stew_ctx) toret.llctx = make_sc_ctx() toret.client_ch = make(chan io.ReadWriteCloser) toret.write_ch = make(chan stew_message) toret.number_ch = make(chan int, 65536) var xaxa sync.Once toret.destroy = func() { xaxa.Do(func() { toret.llctx.destroy() close(toret.killswitch) }) } toret.killswitch = make(chan bool) // Kill when underlying dies go func() { <-toret.llctx.killswitch kilog.Debug("llctx dead") toret.destroy() }() go func() { ctr := uint64(0) for { select { case <-toret.killswitch: return case thing := <-toret.write_ch: //kilog.Debug("Writing stew_message{%d, %d, %s} with ctr %d", thing.category, // thing.connid, string(thing.payload), ctr) scm := sc_message{ctr, thing.bytes()} select { case <-toret.killswitch: return case toret.llctx.write_ch <- scm: // kilog.Debug("Write with ctr=%d went through!", ctr) } } ctr++ } }() for i := 0; i < 16384; i++ { toret.number_ch <- i } return toret }
// applyDeltaOnce pushes one piece of info into the network func (srv *Server) applyDeltaOnce(key ChordKey, meta Neighbor) { kilog.Debug("directory: beginning push to %x", key.ToBytes()) rawsok, err := kiricom.EasyDial(fmt.Sprintf("%v:%v", meta.Address, meta.Port), nil, meta.Secret) if err != nil { kilog.Debug("directory: push to %x failed due to %v", key.ToBytes(), err.Error()) return } defer rawsok.Close() sok, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(meta.PubKey), rawsok) if err != nil { kilog.Debug("directory: push to %x failed in KiSS due to %v", key.ToBytes(), err.Error()) return } defer sok.Close() srv.Lock() neighs, err := srv.crd.Neighs(key) if err != nil { panic("WTF is going on here") } srv.Unlock() var msg textprot.NeighInfo // expires 1hr from now msg.Json.Expires = int(time.Now().Add(time.Hour).Unix()) msg.Json.IssuedTo = meta.PubKey for _, nay := range neighs { msg.Json.NeighList = append(msg.Json.NeighList, nay.ToBytes()) } msg.Signat = srv.prv.Sign(msg.Json.HashValue()) // send the message req := textprot.TextReq{ Verb: "NEIGH_PUSH", Blob: msg.ToString(), } err = req.WriteTo(sok) if err != nil { kilog.Debug("directory: push to %x failed while pushing due to %v", key.ToBytes(), err.Error()) return } //fmt.Println(msg.ToString()) // get msg back err = req.ReadFrom(sok) if err != nil { kilog.Debug("directory: push to %x failed at the final stage", key.ToBytes()) return } kilog.Debug("directory: push to %x succeeded", key.ToBytes()) }
func runCore(id directory.Client) { state := core2core.NewNodeState(dirProvider, id) addr := id.GetAddress() srv, err := kiricom.EasyListen(fmt.Sprintf("0.0.0.0:%v", addr.Port), nil, id.GetSecret()) if err != nil { panic(err.Error()) } err = dirProvider.JoinCore(id) if err != nil { panic(err.Error()) } go func() { for { time.Sleep(time.Minute * 5) err = dirProvider.JoinCore(id) if err != nil { kilog.Warning("core: error while joining %v", err.Error()) } } }() fmt.Println(id.GetAddress()) kilog.Info("started core service on %v", addr) for { client, err := srv.Accept() if err != nil { panic(err.Error()) } kilog.Debug("core: accepted a client") go func() { err := state.HandleClient(client) if err != nil { kilog.Warning("core: error %v", err) } }() } }
func (dpv dftProv) JoinCore(clnt Client) (err error) { sok := dpv.getSock(clnt) if sok == nil { err = errors.New("directory: default provider failed to obtain socket") return } defer sok.Close() // TODO why do we need to make this copy?????? xxx := make([]byte, 4) copy(xxx, clnt.addr.IP.To4()) req := clntRequest{ Code: "CORE", Address: xxx, Port: clnt.addr.Port, Secret: clnt.obfsec, PubKey: clnt.private.PublicKey(), HCSoln: clnt.powork, } kilog.Debug("directory: default provider joining %v", req) err = struc.Pack(sok, &req) if err != nil { return } var iresp srvInitResp err = struc.Unpack(sok, &iresp) if err != nil { return } switch iresp.Code { case "BADP": err = ErrBadPow return case "OKAY": return default: err = errors.New("directory: default provider saw garbage") return } }
// EasyDial dials to a target address (in `host:port` form) using Kiricom over hlObfs. // `secret` may be specified, or it may be nil, in which case the default secret is implied. // // When `verify` is nil, KiSS is not used at all. func EasyDial(targetAddr string, verify kiss.Verifier, secret []byte) (io.ReadWriteCloser, error) { dialState.Lock() res, ok := dialState.table[targetAddr] if !ok { raw, err := net.Dial("tcp", targetAddr) if err != nil { dialState.Unlock() return nil, err } raw.(*net.TCPConn).SetNoDelay(true) sec, err := kiss.LLObfsClientHandshake(secret, raw) if err != nil { dialState.Unlock() return nil, err } if verify != nil { sec, err = kiss.KiSSAnonHandshake(verify, sec) if err != nil { dialState.Unlock() return nil, err } } state := NewClientCtx(32768, sec) dialState.table[targetAddr] = state dialState.Unlock() return state.Dial() } dialState.Unlock() toret, err := res.Dial() if err != nil { kilog.Debug("kiricom: EasyDial error: %v", err.Error()) dialState.Lock() delete(dialState.table, targetAddr) dialState.Unlock() return nil, err } return toret, nil }
func (ctx *stew_ctx) attacht_client(client io.ReadWriteCloser, tgt string) { defer client.Close() // We need to find an appropriate channel slot first! connid := <-ctx.number_ch defer func() { client.Close() ctx.number_ch <- connid }() read_ch := make(chan stew_message, 256) ctx.lock.Lock() ctx.conntable[connid] = read_ch ctx.lock.Unlock() // Send connection request select { case ctx.write_ch <- stew_message{m_open, connid, []byte(tgt)}: case <-ctx.killswitch: kilog.Debug("Returning from attacht_client due to killswitch") return } tunnel_connection(ctx, connid, client) }
func run_client_loop() { listener, err := net.Listen("tcp", MasterConfig.General.SocksAddr) if err != nil { panic(err) } circ_ch <- produce_circ() set_gui_progress(1.0) kilog.Info("Bootstrapping 100%%: client started!") go func() { var haha sync.WaitGroup haha.Add(5) for i := 0; i < 5; i++ { go func() { circ_ch <- produce_circ() haha.Done() }() } haha.Wait() }() for { nconn, err := listener.Accept() if err != nil { kilog.Warning("Problem while accepting client socket: %s", err.Error()) continue } go func() { defer func() { nconn.Close() }() addr, err := socks5.ReadRequest(nconn) if err != nil { kilog.Warning("Problem while reading SOCKS5 request") return } kilog.Debug("Attempting connection to %s...", addr) retry: newcirc := <-circ_ch remote, err := newcirc.SocksAccept(nconn) if err != nil { dirclient.RefreshDirectory() circ_ch <- produce_circ() goto retry } circ_ch <- newcirc defer remote.Close() lenbts := []byte{byte((len(addr) + 1) % 256), byte((len(addr) + 1) / 256)} _, err = remote.Write(lenbts) _, err = remote.Write([]byte(fmt.Sprintf("t%s", addr))) if err != nil { kilog.Debug("Failed to send tunnelling request to %s!", addr) socks5.CompleteRequest(0x03, nconn) return } kilog.Debug("Sent tunneling request") code := make([]byte, 4) _, err = io.ReadFull(remote, code) if err != nil { kilog.Debug("Failed to read response for %s! (%s)", addr, err) socks5.CompleteRequest(0x03, nconn) return } switch string(code) { case "OKAY": kilog.Debug("Successfully tunneled %s!", addr) socks5.CompleteRequest(0x00, nconn) go func() { defer remote.Close() io.Copy(remote, nconn) }() io.Copy(nconn, remote) case "TMOT": kilog.Debug("Tunnel to %s timed out!", addr) socks5.CompleteRequest(0x06, nconn) case "NOIM": kilog.Debug("Tunnel type for %s isn't implemented by server!", addr) socks5.CompleteRequest(0x07, nconn) case "FAIL": kilog.Debug("Tunnel to %s cannot be established!", addr) socks5.CompleteRequest(0x04, nconn) default: kilog.Debug("Protocol error on tunnel to %s! (%s)", addr, string(code)) socks5.CompleteRequest(0x01, nconn) return } }() } }
// EasyListen listens for incoming kiricom connections. // // If privkey is nil, then no KiSS would be done, just obfuscation. func EasyListen(addr string, privkey natrium.EdDSAPrivate, secret []byte) (toret *EasyListener, err error) { tcpadd, err := net.ResolveTCPAddr("tcp", addr) if err != nil { return } toret = new(EasyListener) toret.Addr = tcpadd toret.Secret = secret toret.core, err = net.ListenTCP("tcp", tcpadd) if err != nil { return } toret.deadch = make(chan bool) toret.sockch = make(chan io.ReadWriteCloser) go func() { for { lol, err := toret.core.Accept() if err != nil { return } lol.(*net.TCPConn).SetNoDelay(true) go func() { obfs, err := kiss.LLObfsServerHandshake(secret, lol) if err != nil { kilog.FineDebug("kiricom: EasyListen failed HLObfs: %v", err) lol.Close() return } if privkey != nil { kss, err := kiss.KiSSNamedHandshake(privkey, nil, obfs) if err != nil { kilog.FineDebug("kiricom: EasyListen failed KiSS: %v", kss) obfs.Close() return } obfs = kss } state := NewServerCtx(32768, obfs) go func() { <-toret.deadch state.Close() }() defer state.Close() for { sok, err := state.Accept() if err != nil { kilog.Debug("kiricom: EasyListen internal accept error %v", err.Error()) return } select { case toret.sockch <- sok: case <-toret.deadch: return } } }() } }() return toret, nil }
func handleSocks(clnt io.ReadWriteCloser) { defer clnt.Close() defer kilog.Debug("exited handleSocks") destin, err := socks5.ReadRequest(clnt) if err != nil { kilog.Warning("problem while reading SOCKS5 request: %v", err.Error()) return } kilog.Debug("SOCKS beginning to handle %v", destin) if !sagiriNames.CheckEdgeID(destin) { kilog.Warning("invalid name (%v) sent to SOCKS subsystem, misconfig?", destin) // 0x08, address type not supported socks5.CompleteRequest(0x08, clnt) return } parsed := sagiriNames.ParseEdgeID(destin) if parsed.IPAddress == nil { /*kilog.Warning("SOCKS only supports direct connections currently, refusing!") // 0x08, address type not supported socks5.CompleteRequest(0x08, clnt) return*/ remote, err := dialPubKey(parsed.PubKey) if err != nil { kilog.Debug("SOCKS failed to connect to remote anon host (%v)", err) return } defer remote.Close() err = socks5.CompleteRequest(0x00, clnt) if err != nil { kilog.Debug("SOCKS failed to send back response (%v)", err) return } // forward between local and remote go func() { defer clnt.Close() defer remote.Close() io.Copy(remote, clnt) }() io.Copy(clnt, remote) } else { kiriaddr := fmt.Sprintf("%v:%v", parsed.IPAddress, parsed.PortNum) secret := parsed.PubKey // verifier function verifier := func(other natrium.EdDSAPublic) bool { return subtle.ConstantTimeCompare(other, parsed.PubKey) == 1 } remote, err := kiricom.EasyDial(kiriaddr, verifier, secret) if err != nil { kilog.Debug("SOCKS failed to connect to remote host (%v)", err) // 0x04, host unreachable socks5.CompleteRequest(0x04, clnt) return } kilog.Debug("SOCKS succesfully connected to %v:%v on ICOM", parsed.IPAddress, parsed.PortNum) defer remote.Close() err = socks5.CompleteRequest(0x00, clnt) if err != nil { kilog.Debug("SOCKS failed to send back response (%v)", err) return } kilog.Debug("SOCKS successfully sent back response") // forward between local and remote go func() { defer clnt.Close() defer remote.Close() io.Copy(remote, clnt) }() io.Copy(clnt, remote) } }