From 56676002aadacbe370d47c7402f71147fd122af5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 14 Nov 2018 14:34:17 -0500 Subject: [PATCH] wire up exit traffic --- daemon/rcutil.cpp | 6 +- include/llarp/encode.hpp | 4 +- include/llarp/exit/session.hpp | 32 +++++++--- include/llarp/exit_info.hpp | 12 +++- include/llarp/handlers/tun.hpp | 12 ++++ include/llarp/path.hpp | 12 ++-- include/llarp/service/endpoint.hpp | 3 + llarp/encode.cpp | 8 ++- llarp/exit/session.cpp | 99 +++++++++++++++++++++++++++++- llarp/handlers/tun.cpp | 23 ++++++- llarp/path.cpp | 8 +++ llarp/router.cpp | 11 +++- llarp/router.hpp | 10 +++ 13 files changed, 214 insertions(+), 26 deletions(-) diff --git a/daemon/rcutil.cpp b/daemon/rcutil.cpp index 7fcc7d3db..0ac78aa04 100644 --- a/daemon/rcutil.cpp +++ b/daemon/rcutil.cpp @@ -492,7 +492,7 @@ main(int argc, char *argv[]) // llarp::LogInfo("Looking for string: ", rcfname); llarp::PubKey binaryPK; - llarp::HexDecode(rcfname, binaryPK.data()); + llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size()); llarp::LogInfo("Looking for binary: ", binaryPK); llarp::RouterContact *rc = llarp_main_getDatabase(ctx, binaryPK.data()); @@ -513,7 +513,7 @@ main(int argc, char *argv[]) llarp_main_setup(ctx); llarp::PubKey binaryPK; - llarp::HexDecode(rcfname, binaryPK.data()); + llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size()); llarp::LogInfo("Queueing job"); llarp_router_lookup_job *job = new llarp_router_lookup_job; @@ -584,7 +584,7 @@ main(int argc, char *argv[]) llarp::PubKey binaryPK; // llarp::service::Address::FromString - llarp::HexDecode(rcfname, binaryPK.data()); + llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size()); char tmp[(1 + 32) * 2] = {0}; std::string b32 = llarp::Base32Encode(binaryPK, tmp); llarp::LogInfo("to base32 ", b32); diff --git a/include/llarp/encode.hpp b/include/llarp/encode.hpp index 9ef952382..a7a737064 100644 --- a/include/llarp/encode.hpp +++ b/include/llarp/encode.hpp @@ -133,8 +133,8 @@ namespace llarp int char2int(char input); - void - HexDecode(const char* src, uint8_t* target); + bool + HexDecode(const char* src, uint8_t* target, size_t sz); } // namespace llarp #endif diff --git a/include/llarp/exit/session.hpp b/include/llarp/exit/session.hpp index 9a42117be..3d4043605 100644 --- a/include/llarp/exit/session.hpp +++ b/include/llarp/exit/session.hpp @@ -1,6 +1,7 @@ #ifndef LLARP_EXIT_SESSION_HPP #define LLARP_EXIT_SESSION_HPP #include +#include namespace llarp { @@ -9,8 +10,9 @@ namespace llarp /// a persisiting exit session with an exit router struct BaseSession : public llarp::path::Builder { - BaseSession(const llarp::RouterID& exitRouter, llarp_router* r, - size_t numpaths, size_t hoplen); + BaseSession(const llarp::RouterID& exitRouter, + std::function< bool(llarp_buffer_t) > writepkt, + llarp_router* r, size_t numpaths, size_t hoplen); ~BaseSession(); @@ -18,18 +20,28 @@ namespace llarp SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur, size_t hop, llarp::path::PathRole roles) override; + void + HandlePathBuilt(llarp::path::Path* p) override; + + bool + SendUpstreamTraffic(llarp::net::IPv4Packet pkt); + protected: llarp::RouterID m_ExitRouter; - }; + std::function< bool(llarp_buffer_t) > m_WritePacket; - /// a N-hop exit sesssion form a client - struct ClientSesssion final : public BaseSession - { - }; + bool + HandleTrafficDrop(llarp::path::Path* p, const llarp::PathID_t& path, + uint64_t s); - /// a "direct" session between service nodes - struct DirectSession final : public BaseSession - { + bool + HandleGotExit(llarp::path::Path* p, llarp_time_t b); + + bool + HandleTraffic(llarp::path::Path* p, llarp_buffer_t buf); + + private: + llarp::SecretKey m_ExitIdentity; }; } // namespace exit diff --git a/include/llarp/exit_info.hpp b/include/llarp/exit_info.hpp index 6465702de..f335d595a 100644 --- a/include/llarp/exit_info.hpp +++ b/include/llarp/exit_info.hpp @@ -2,7 +2,7 @@ #define LLARP_XI_HPP #include #include -#include +#include #include #include @@ -21,6 +21,16 @@ namespace llarp struct in6_addr netmask; PubKey pubkey; + ExitInfo(const PubKey &pk, const nuint32_t &ipv4_exit) : IBEncodeMessage() + { + pubkey = pk; + memset(address.s6_addr, 0, 16); + address.s6_addr[11] = 0xff; + address.s6_addr[10] = 0xff; + memcpy(address.s6_addr + 12, &ipv4_exit, 4); + memset(netmask.s6_addr, 0xff, 16); + } + ExitInfo() : IBEncodeMessage() { } diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index 1a6a893d4..6ad291522 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -152,6 +152,18 @@ namespace llarp m_AddrToIP; private: + bool + QueueInboundPacketForExit(llarp_buffer_t buf) + { + return m_NetworkToUserPktQueue.EmplaceIf( + [&](llarp::net::IPv4Packet& pkt) -> bool { + if(!pkt.Load(buf)) + return false; + pkt.UpdateIPv4PacketOnDst(pkt.src(), m_OurIP); + return true; + }); + } + #ifndef WIN32 /// handles setup, given value true on success and false on failure to set /// up interface diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index e511d4489..b51d82165 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -469,11 +469,15 @@ namespace llarp std::string Name() const; - /// ask endpoint for exit - /// call handler with result when we get it - /// returns false if we failed to send the OXM + void + AddObtainExitHandler(ObtainedExitHandler handler) + { + m_ObtainedExitHooks.push_back(handler); + } + bool - ObtainExit(llarp_router* r, ObtainedExitHandler handler) const; + SendExitRequest(const llarp::routing::ObtainExitMessage* msg, + llarp_router* r); protected: llarp::routing::InboundMessageParser m_InboundMessageParser; diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index c4fbeda5f..c79c1aacd 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include // minimum time between interoset shifts #ifndef MIN_SHIFT_INTERVAL @@ -414,6 +416,7 @@ namespace llarp protected: IDataHandler* m_DataHandler = nullptr; Identity m_Identity; + std::unique_ptr< llarp::exit::BaseSession > m_Exit; private: llarp_router* m_Router; diff --git a/llarp/encode.cpp b/llarp/encode.cpp index f1f8cd1c0..c9cba9eb9 100644 --- a/llarp/encode.cpp +++ b/llarp/encode.cpp @@ -15,13 +15,15 @@ namespace llarp return 0; } - void - HexDecode(const char* src, uint8_t* target) + bool + HexDecode(const char* src, uint8_t* target, size_t sz) { - while(*src && src[1]) + while(*src && src[1] && sz) { *(target++) = char2int(*src) * 16 + char2int(src[1]); src += 2; + --sz; } + return sz == 0; } } // namespace llarp diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index a62fdf9c9..38639c020 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -1,8 +1,105 @@ #include +#include "router.hpp" namespace llarp { namespace exit { - } + BaseSession::BaseSession(const llarp::RouterID& router, + std::function< bool(llarp_buffer_t) > writepkt, + llarp_router* r, size_t numpaths, size_t hoplen) + : llarp::path::Builder(r, r->dht, numpaths, hoplen) + , m_ExitRouter(router) + , m_WritePacket(writepkt) + { + r->crypto.identity_keygen(m_ExitIdentity); + } + + BaseSession::~BaseSession() + { + } + + bool + BaseSession::SelectHop(llarp_nodedb* db, const RouterContact& prev, + RouterContact& cur, size_t hop, + llarp::path::PathRole roles) + { + if(hop == numHops - 1) + return llarp_nodedb_get_rc(db, m_ExitRouter, cur); + else + return path::Builder::SelectHop(db, prev, cur, hop, roles); + } + + void + BaseSession::HandlePathBuilt(llarp::path::Path* p) + { + p->SetDropHandler(std::bind(&BaseSession::HandleTrafficDrop, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); + p->SetExitTrafficHandler(std::bind(&BaseSession::HandleTraffic, this, + std::placeholders::_1, + std::placeholders::_2)); + p->AddObtainExitHandler(std::bind(&BaseSession::HandleGotExit, this, + std::placeholders::_1, + std::placeholders::_2)); + llarp::routing::ObtainExitMessage obtain; + obtain.S = p->NextSeqNo(); + obtain.T = llarp_randint(); + obtain.X = 0; + if(!obtain.Sign(&router->crypto, m_ExitIdentity)) + { + llarp::LogError("Failed to sign exit request"); + return; + } + if(p->SendExitRequest(&obtain, router)) + llarp::LogInfo("asking ", m_ExitRouter, " for exit"); + else + llarp::LogError("faild to send exit request"); + } + + bool + BaseSession::HandleGotExit(llarp::path::Path* p, llarp_time_t b) + { + if(b == 0) + { + llarp::LogInfo("obtained an exit via ", p->Endpoint()); + } + return true; + } + + bool + BaseSession::HandleTraffic(llarp::path::Path* p, llarp_buffer_t pkt) + { + (void)p; + if(m_WritePacket) + return m_WritePacket(pkt); + return false; + } + + bool + BaseSession::HandleTrafficDrop(llarp::path::Path* p, const PathID_t& path, + uint64_t s) + { + (void)p; + llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, + " P=", path); + return true; + } + + bool + BaseSession::SendUpstreamTraffic(llarp::net::IPv4Packet pkt) + { + auto path = PickRandomEstablishedPath(llarp::path::ePathRoleExit); + if(!path) + return false; + llarp::routing::TransferTrafficMessage transfer; + transfer.S = path->NextSeqNo(); + transfer.X.resize(pkt.sz); + memcpy(transfer.X.data(), pkt.buf, pkt.sz); + if(!transfer.Sign(&router->crypto, m_ExitIdentity)) + return false; + return path->SendRoutingMessage(&transfer, router); + } + + } // namespace exit } // namespace llarp \ No newline at end of file diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index f54f7b84f..d1fe0a274 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -37,6 +37,21 @@ namespace llarp bool TunEndpoint::SetOption(const std::string &k, const std::string &v) { + if(k == "exit-node") + { + llarp::RouterID exitRouter; + if(!HexDecode(v.c_str(), exitRouter, exitRouter.size())) + { + llarp::LogError(Name(), " bad exit router key: ", v); + return false; + } + m_Exit.reset(new llarp::exit::BaseSession( + exitRouter, + std::bind(&TunEndpoint::QueueInboundPacketForExit, this, + std::placeholders::_1), + router, m_NumPaths, numHops)); + llarp::LogInfo(Name(), " using exit at ", exitRouter); + } if(k == "local-dns") { std::string resolverAddr = v; @@ -338,7 +353,13 @@ namespace llarp auto itr = m_IPToAddr.find(pkt.dst()); if(itr == m_IPToAddr.end()) { - llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst()); + if(m_Exit) + { + pkt.UpdateIPv4PacketOnDst({0}, pkt.dst()); + m_Exit->SendUpstreamTraffic(std::move(pkt)); + } + else + llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst()); return true; } diff --git a/llarp/path.cpp b/llarp/path.cpp index 9d2b76876..d2f8c3a32 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -702,6 +702,14 @@ namespace llarp return false; } + bool + Path::SendExitRequest(const llarp::routing::ObtainExitMessage* msg, + llarp_router* r) + { + m_ExitObtainTX = msg->T; + return SendRoutingMessage(msg, r); + } + bool Path::HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg, llarp_router* r) diff --git a/llarp/router.cpp b/llarp/router.cpp index 2b8886505..d3497a469 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -751,7 +751,16 @@ llarp_router::Run() // set public signing key _rc.pubkey = llarp::seckey_topublic(identity); llarp::LogInfo("Your Identity pubkey ", rc().pubkey); - + if(ExitEnabled()) + { + llarp::nuint32_t a = publicAddr.xtonl(); + // TODO: enable this once the network can serialize xi + //_rc.exits.emplace_back(_rc.pubkey, a); + llarp::LogInfo( + "Neato tehl33toh, You are a freaking exit relay. w00t!!!!! your exit " + "is advertised as exiting at ", + a); + } llarp::LogInfo("Signing rc..."); if(!_rc.Sign(&crypto, identity)) { diff --git a/llarp/router.hpp b/llarp/router.hpp index 92ca715b4..b0daaf82e 100644 --- a/llarp/router.hpp +++ b/llarp/router.hpp @@ -25,6 +25,7 @@ #include "crypto.hpp" #include "fs.hpp" #include "mem.hpp" +#include "str.hpp" bool llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath, @@ -102,6 +103,15 @@ struct llarp_router /// default exit config llarp::exit::Context::Config_t exitConf; + bool + ExitEnabled() const + { + auto itr = exitConf.find("exit"); + if(itr == exitConf.end()) + return false; + return llarp::IsTrueValue(itr->second.c_str()); + } + bool CreateDefaultHiddenService();