// 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()) }
// NewClient creates a client from the given first-node information. func NewClient(first directory.Neighbor) (toret *Client, err error) { // kissless kiricom sok, err := kiricom.EasyDial( fmt.Sprintf("%v:%v", first.Address, first.Port), nil, first.Secret) if err != nil { return } // negotiate KiSS secsok, err := kiss.KiSSAnonHandshake(kiss.NewDirectVerifier(first.PubKey), sok) if err != nil { return } // return the client toret = &Client{ sok: secsok, pklst: []natrium.EdDSAPublic{first.PubKey}, } return }
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) } }
func (ns *NodeState) do_NEIGH_CONNECT(sok io.ReadWriteCloser, req textprot.TextReq) (err error) { // decode the hex if len(req.Args) == 0 { err = errors.New("core2core: server got truncated NEIGH_CONNECT") return } hexstr := req.Args[0] bts, err := hex.DecodeString(hexstr) if err != nil { return } kilog.Debug("core2core: NEIGH_CONNECT received to %x", bts) // read-lock the state; release when done searching ns.RLock() // linear search for the next hop found := false var nxtneigh directory.Neighbor for _, val := range ns.fulNeighs { if subtle.ConstantTimeCompare(val.PubKey, bts) == 1 { nxtneigh = val found = found || true // don't break, precaution against side channels } else { found = found || false } } ns.RUnlock() if !found { response := textprot.TextReq{ Verb: "NOPE", } err = response.WriteTo(sok) kilog.Debug("core2core: NEIGH_CONNECT to %x failed due to not found", bts) return } // easydial to the next hop hostport := fmt.Sprintf("%v:%v", nxtneigh.Address, nxtneigh.Port) nxtsok, err := kiricom.EasyDial(hostport, nil, nxtneigh.Secret) if err != nil { return } defer nxtsok.Close() // reply OKAY response := textprot.TextReq{ Verb: "OKAY", } err = response.WriteTo(sok) if err != nil { return } kilog.Debug("core2core: NEIGH_CONNECT success to %x", bts) // begin tunneling go func() { defer nxtsok.Close() defer sok.Close() io.Copy(nxtsok, sok) }() defer sok.Close() io.Copy(sok, nxtsok) return nil }