initial exit/service node comm code with some unit tests (incomplete)

pull/52/head
Jeff Becker 6 years ago
parent 0eacab7759
commit 09945dce62
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -455,6 +455,17 @@ set(LIB_SRC
llarp/dht/got_intro.cpp
llarp/dht/got_router.cpp
llarp/dht/publish_intro.cpp
llarp/exit/close_exit.cpp
llarp/exit/context.cpp
llarp/exit/endpoint.cpp
llarp/exit/grant_exit.cpp
llarp/exit/update_exit.cpp
llarp/exit/obtain_exit.cpp
llarp/exit/policy.cpp
llarp/exit/reject_exit.cpp
llarp/exit/session.cpp
llarp/exit/transfer_traffic.cpp
llarp/handlers/exit.cpp
llarp/handlers/tun.cpp
llarp/link/curvecp.cpp
llarp/link/server.cpp
@ -494,6 +505,8 @@ set(TEST_SRC
test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
test/hiddenservice_unittest.cpp
test/traffic_transfer_unittest.cpp
test/obtain_exit_unittest.cpp
test/pq_unittest.cpp
test/net_unittest.cpp
test/test_dns_unit.cpp

@ -526,7 +526,7 @@ variant 2, response, generated by the endpoint that recieved the request.
V: 0
}
obtain exit address message (OXAM)
obtain exit message (OXM)
sent to an exit router to obtain ip exit traffic context.
replies are sent down the path that messages originate from.
@ -544,9 +544,9 @@ replies are sent down the path that messages originate from.
Z: "<64 bytes signature using I>"
}
grant exit address messsage (GXAM)
grant exit messsage (GXM)
sent in response to an OXAM to grant an ip for exit traffic from an external
sent in response to an OXM to grant an ip for exit traffic from an external
ip address used for exit traffic.
{
@ -561,7 +561,7 @@ any TITM recieved on the same path will be forwarded out to the internet if
OXAM.E is not 0, otherwise it is interpreted as service node traffic.
reject exit address message (RXAM)
reject exit message (RXM)
sent in response to an OXAM to indicate that exit traffic is not allowed or
was denied.

@ -0,0 +1,6 @@
#ifndef LLARP_EXIT_HPP
#define LLARP_EXIT_HPP
#include <llarp/exit/context.hpp>
#include <llarp/exit/policy.hpp>
#include <llarp/exit/session.hpp>
#endif

@ -0,0 +1,36 @@
#ifndef LLARP_EXIT_CONTEXT_HPP
#define LLARP_EXIT_CONTEXT_HPP
#include <llarp/exit/policy.hpp>
#include <string>
#include <unordered_map>
#include <llarp/handlers/exit.hpp>
#include <llarp/router.h>
namespace llarp
{
namespace exit
{
/// owner of all the exit endpoints
struct Context
{
using Config_t = std::unordered_multimap< std::string, std::string >;
Context(llarp_router *r);
~Context();
void
Tick(llarp_time_t now);
bool
AddExitEndpoint(const std::string &name, const Config_t &config);
private:
llarp_router *m_Router;
std::unordered_map< std::string,
std::unique_ptr< llarp::handlers::ExitEndpoint > >
m_Exits;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,54 @@
#ifndef LLARP_EXIT_ENDPOINT_HPP
#define LLARP_EXIT_ENDPOINT_HPP
#include <llarp/time.h>
#include <llarp/crypto.hpp>
#include <llarp/router.h>
#include <llarp/path.hpp>
namespace llarp
{
namespace handlers
{
// forward declare
struct ExitEndpoint;
} // namespace handlers
namespace exit
{
/// persistant exit state for 1 identity on the exit node
struct Endpoint
{
Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath,
llarp::handlers::ExitEndpoint* parent);
~Endpoint();
/// return true if we are expired right now
bool
IsExpired(llarp_time_t now) const;
/// handle traffic from service node / internet
bool
SendInboundTraffic(llarp_buffer_t buff);
/// send traffic to service node / internet
/// does ip rewrite
bool
SendOutboundTraffic(llarp_buffer_t buf);
void
UpdateLocalPath(const llarp::PathID_t& nextPath);
llarp::path::IHopHandler*
GetCurrentPath() const;
private:
llarp::handlers::ExitEndpoint* m_Parent;
llarp::PubKey m_remoteSignKey;
llarp::PathID_t m_CurrentPath;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,26 @@
#ifndef LLARP_EXIT_POLICY_HPP
#define LLARP_EXIT_POLICY_HPP
#include <llarp/bencode.hpp>
namespace llarp
{
namespace exit
{
struct Policy final : public llarp::IBEncodeMessage
{
~Policy();
uint64_t proto;
uint64_t port;
uint64_t drop;
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
bool
BEncode(llarp_buffer_t* buf) const override;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,38 @@
#ifndef LLARP_EXIT_SESSION_HPP
#define LLARP_EXIT_SESSION_HPP
#include <llarp/pathbuilder.hpp>
namespace llarp
{
namespace exit
{
/// 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();
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop) override;
protected:
llarp::RouterID m_ExitRouter;
};
/// a N-hop exit sesssion form a client
struct ClientSesssion final : public BaseSession
{
};
/// a "direct" session between service nodes
struct DirectSession final : public BaseSession
{
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,44 @@
#ifndef LLARP_HANDLERS_EXIT_HPP
#define LLARP_HANDLERS_EXIT_HPP
#include <llarp/handlers/tun.hpp>
#include <llarp/exit/endpoint.hpp>
#include <unordered_map>
namespace llarp
{
namespace handlers
{
struct ExitEndpoint final : public TunEndpoint
{
ExitEndpoint(const std::string& name, llarp_router* r);
~ExitEndpoint();
void
Tick(llarp_time_t now) override;
bool
SetOption(const std::string& k, const std::string& v) override;
virtual std::string
Name() const override;
protected:
void
FlushSend();
private:
std::string m_Name;
std::unordered_multimap< llarp::PubKey, llarp::exit::Endpoint,
llarp::PubKey::Hash >
m_ActiveExits;
std::unordered_map< llarp::huint32_t, llarp::PubKey,
llarp::huint32_t::Hash >
m_AddrsToPubKey;
};
} // namespace handlers
} // namespace llarp
#endif

@ -23,10 +23,10 @@ namespace llarp
TunEndpoint(const std::string& nickname, llarp_router* r);
~TunEndpoint();
bool
virtual bool
SetOption(const std::string& k, const std::string& v);
void
virtual void
Tick(llarp_time_t now);
void
@ -115,7 +115,8 @@ namespace llarp
void
MarkIPActiveForever(huint32_t ip);
void
/// flush ip packets
virtual void
FlushSend();
private:

@ -11,5 +11,7 @@
#include <llarp/messages/relay_commit.hpp>
#include <llarp/messages/discard.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/exit.hpp>
#include <llarp/messages/transfer_traffic.hpp>
#endif

@ -0,0 +1,133 @@
#ifndef LLARP_MESSAGES_EXIT_HPP
#define LLARP_MESSAGES_EXIT_HPP
#include <llarp/routing/message.hpp>
#include <llarp/exit/policy.hpp>
#include <vector>
#include <llarp/crypto.hpp>
namespace llarp
{
namespace routing
{
struct ObtainExitMessage final : public IMessage
{
std::vector< llarp::exit::Policy > B;
uint64_t E;
llarp::PubKey I;
uint64_t T;
std::vector< llarp::exit::Policy > W;
llarp_time_t X;
llarp::Signature Z;
ObtainExitMessage() : IMessage()
{
}
~ObtainExitMessage()
{
}
ObtainExitMessage&
operator=(const ObtainExitMessage& other);
/// populates I and signs
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct GrantExitMessage final : public IMessage
{
GrantExitMessage() : IMessage()
{
}
~GrantExitMessage()
{
}
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct RejectExitMessage final : public IMessage
{
RejectExitMessage() : IMessage()
{
}
~RejectExitMessage()
{
}
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct UpdateExitMessage final : public IMessage
{
UpdateExitMessage() : IMessage()
{
}
~UpdateExitMessage()
{
}
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct CloseExitMessage final : public IMessage
{
CloseExitMessage() : IMessage()
{
}
~CloseExitMessage()
{
}
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
} // namespace routing
} // namespace llarp
#endif

@ -0,0 +1,41 @@
#ifndef LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
#define LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
#include <llarp/routing/message.hpp>
#include <llarp/crypto.hpp>
#include <vector>
namespace llarp
{
namespace routing
{
constexpr size_t MaxExitMTU = 1500;
struct TransferTrafficMessage final : public IMessage
{
std::vector< byte_t > X;
llarp::Signature Z;
TransferTrafficMessage&
operator=(const TransferTrafficMessage& other);
bool
PutBuffer(llarp_buffer_t buf);
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
} // namespace routing
} // namespace llarp
#endif

@ -106,7 +106,8 @@ namespace llarp
/// send routing message and increment sequence number
virtual bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r) = 0;
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) = 0;
// handle data in upstream direction
virtual bool
@ -118,6 +119,12 @@ namespace llarp
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
uint64_t
NextSeqNo()
{
return m_SequenceNum++;
}
protected:
uint64_t m_SequenceNum = 0;
};
@ -159,7 +166,7 @@ namespace llarp
// send routing message when end of path
bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r);
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
// handle routing message when end of path
bool
@ -180,6 +187,29 @@ namespace llarp
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg,
llarp_router* r);
bool
HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r);
bool
HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg, llarp_router* r);
bool
HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage* msg,
llarp_router* r);
bool
HandleGrantExitMessage(const llarp::routing::GrantExitMessage* msg,
llarp_router* r);
bool
HandleRejectExitMessage(const llarp::routing::RejectExitMessage* msg,
llarp_router* r);
bool
HandleCloseExitMessage(const llarp::routing::CloseExitMessage* msg,
llarp_router* r);
bool
HandleHiddenServiceFrame(__attribute__((unused))
const llarp::service::ProtocolFrame* frame)
@ -287,7 +317,33 @@ namespace llarp
Tick(llarp_time_t now, llarp_router* r);
bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r);
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
bool
HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r);
bool
HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg, llarp_router* r);
bool
HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage* msg,
llarp_router* r);
bool
HandleCloseExitMessage(const llarp::routing::CloseExitMessage* msg,
llarp_router* r);
bool
HandleRejectExitMessagge(const llarp::routing::RejectExitMessage* msg,
llarp_router* r);
bool
HandleGrantExitMessage(const llarp::routing::GrantExitMessage* msg,
llarp_router* r);
bool
HandleRejectExitMessage(const llarp::routing::RejectExitMessage* msg,
llarp_router* r);
bool
HandleDataDiscardMessage(const llarp::routing::DataDiscardMessage* msg,
@ -392,6 +448,7 @@ namespace llarp
void
AllowTransit();
void
RejectTransit();

@ -7,8 +7,9 @@
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/path_latency.hpp>
#include <llarp/messages/path_transfer.hpp>
#include <llarp/messages/exit.hpp>
#include <llarp/messages/transfer_traffic.hpp>
namespace llarp
{
@ -19,6 +20,28 @@ namespace llarp
// handles messages on the routing level
struct IMessageHandler
{
virtual bool
HandleObtainExitMessage(const ObtainExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleGrantExitMessage(const GrantExitMessage *msg, llarp_router *r) = 0;
virtual bool
HandleRejectExitMessage(const RejectExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleTransferTrafficMessage(const TransferTrafficMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleUpdateExitMessage(const UpdateExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleCloseExitMessage(const CloseExitMessage *msg, llarp_router *r) = 0;
virtual bool
HandleDataDiscardMessage(const DataDiscardMessage *msg,
llarp_router *r) = 0;

@ -18,7 +18,7 @@ namespace llarp
~Context();
void
Tick();
Tick(llarp_time_t now);
bool
hasEndpoints();

@ -78,7 +78,7 @@ namespace llarp
return false;
}
std::string
virtual std::string
Name() const;
bool
@ -139,6 +139,9 @@ namespace llarp
return true;
}
bool
HandleDataMessage(const PathID_t&);
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);

@ -183,6 +183,13 @@ llarp_ensure_router_config(std::ofstream &f, std::string basepath)
f << "# network settings " << std::endl;
f << "[network]" << std::endl;
f << "profiles=" << basepath << "profiles.dat" << std::endl;
f << "ifaddr=10.105.0.1/16" << std::endl;
f << "ifname=lokitun0" << std::endl;
f << "enabled=true" << std::endl;
f << "exit=false" << std::endl;
f << "# exit-blacklist=tcp:25" << std::endl;
f << "# exit-whitelist=tcp:*" << std::endl;
f << "# exit-whitelist=udp:*" << std::endl;
f << std::endl;
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic"
<< std::endl;

@ -0,0 +1,32 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
CloseExitMessage::BEncode(llarp_buffer_t* buf) const
{
(void)buf;
// TODO: implement me
return false;
}
bool
CloseExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
(void)k;
(void)buf;
// TODO: implement me
return false;
}
bool
CloseExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleCloseExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,56 @@
#include <llarp/exit/context.hpp>
namespace llarp
{
namespace exit
{
Context::Context(llarp_router* r) : m_Router(r)
{
}
Context::~Context()
{
}
void
Context::Tick(llarp_time_t now)
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
itr->second->Tick(now);
++itr;
}
}
bool
Context::AddExitEndpoint(const std::string& name, const Config_t& conf)
{
// check for duplicate exit by name
{
auto itr = m_Exits.find(name);
if(itr != m_Exits.end())
{
llarp::LogError("duplicate exit with name ", name);
return false;
}
}
std::unique_ptr< llarp::handlers::ExitEndpoint > endpoint;
// make new endpoint
endpoint.reset(new llarp::handlers::ExitEndpoint(name, m_Router));
// configure
{
auto itr = conf.begin();
while(itr != conf.end())
{
if(!endpoint->SetOption(itr->first, itr->second))
return false;
++itr;
}
}
// add endpoint
m_Exits.emplace(name, std::move(endpoint));
return true;
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,48 @@
#include <llarp/exit/endpoint.hpp>
#include "router.hpp"
namespace llarp
{
namespace exit
{
Endpoint::~Endpoint()
{
}
bool
Endpoint::IsExpired(llarp_time_t now) const
{
auto path = GetCurrentPath();
if(path)
{
return path->Expired(now);
}
// if we don't have an underlying path we are considered expired
return true;
}
bool
Endpoint::SendInboundTraffic(llarp_buffer_t buf)
{
auto path = GetCurrentPath();
if(path)
{
llarp::routing::TransferTrafficMessage msg;
if(!msg.PutBuffer(buf))
return false;
msg.S = path->NextSeqNo();
if(!msg.Sign(m_Parent->Crypto(), m_Parent->Router()->identity))
return false;
return path->SendRoutingMessage(&msg, m_Parent->Router());
}
return false;
}
llarp::path::IHopHandler*
Endpoint::GetCurrentPath() const
{
auto router = m_Parent->Router();
return router->paths.GetByUpstream(router->pubkey(), m_CurrentPath);
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,32 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
GrantExitMessage::BEncode(llarp_buffer_t* buf) const
{
(void)buf;
// TODO: implement me
return false;
}
bool
GrantExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
(void)k;
(void)buf;
// TODO: implement me
return false;
}
bool
GrantExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleGrantExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,112 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/link_layer.hpp>
namespace llarp
{
namespace routing
{
ObtainExitMessage&
ObtainExitMessage::operator=(const ObtainExitMessage& other)
{
B = other.B;
E = other.E;
I = other.I;
T = other.T;
W = other.W;
X = other.X;
version = other.version;
S = other.S;
Z = other.Z;
return *this;
}
bool
ObtainExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[MAX_LINK_MSG_SIZE - 128] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
I = llarp::seckey_topublic(sk);
Z.Zero();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
bool
ObtainExitMessage::Verify(llarp_crypto* c) const
{
byte_t tmp[MAX_LINK_MSG_SIZE - 128] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
ObtainExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
return c->verify(I, buf, Z);
}
bool
ObtainExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "X"))
return false;
if(!BEncodeWriteDictArray("B", B, buf))
return false;
if(!BEncodeWriteDictInt("E", E, buf))
return false;
if(!BEncodeWriteDictEntry("I", I, buf))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictArray("W", W, buf))
return false;
if(!BEncodeWriteDictInt("X", X, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
ObtainExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictList("B", B, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("E", E, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("I", I, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictList("W", W, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("X", X, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
bool
ObtainExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleObtainExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,43 @@
#include <llarp/exit/policy.hpp>
namespace llarp
{
namespace exit
{
Policy::~Policy()
{
}
bool
Policy::BEncode(llarp_buffer_t *buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictInt("a", proto, buf))
return false;
if(!BEncodeWriteDictInt("b", port, buf))
return false;
if(!BEncodeWriteDictInt("d", drop, buf))
return false;
if(!BEncodeWriteDictInt("v", version, buf))
return false;
return bencode_end(buf);
}
bool
Policy::DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("a", proto, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("b", port, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("d", drop, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
return false;
return read;
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,33 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
RejectExitMessage::BEncode(llarp_buffer_t* buf) const
{
(void)buf;
// TODO: implement me
return false;
}
bool
RejectExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
(void)k;
(void)buf;
// TODO: implement me
return false;
}
bool
RejectExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleRejectExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,8 @@
#include <llarp/exit/session.hpp>
namespace llarp
{
namespace exit
{
}
} // namespace llarp

@ -0,0 +1,117 @@
#include <llarp/messages/transfer_traffic.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
TransferTrafficMessage::Sign(llarp_crypto* c, const llarp::SecretKey& k)
{
byte_t tmp[MaxExitMTU + 512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
llarp::Signature sig;
// zero out sig
Z.Zero();
if(!BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
if(!c->sign(sig, k, buf))
return false;
Z = sig;
return true;
}
TransferTrafficMessage&
TransferTrafficMessage::operator=(const TransferTrafficMessage& other)
{
Z = other.Z;
S = other.S;
version = other.version;
X = other.X;
return *this;
}
bool
TransferTrafficMessage::Verify(llarp_crypto* c,
const llarp::PubKey& pk) const
{
byte_t tmp[MaxExitMTU + 512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
llarp::Signature sig;
// make copy
TransferTrafficMessage copy;
copy = *this;
// zero copy's sig
copy.Z.Zero();
// encode
if(!copy.BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
// verify signature
return c->verify(pk, buf, Z);
}
bool
TransferTrafficMessage::PutBuffer(llarp_buffer_t buf)
{
if(buf.sz > MaxExitMTU)
return false;
X.resize(buf.sz);
memcpy(X.data(), buf.base, buf.sz);
return true;
}
bool
TransferTrafficMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "I"))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!bencode_write_bytestring(buf, "X", 1))
return false;
if(!bencode_write_bytestring(buf, X.data(), X.size()))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
TransferTrafficMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, buf))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, key, buf))
return false;
if(llarp_buffer_eq(key, "X"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
return PutBuffer(strbuf);
}
return read;
}
bool
TransferTrafficMessage::HandleMessage(IMessageHandler* h,
llarp_router* r) const
{
return h->HandleTransferTrafficMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,32 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
UpdateExitMessage::BEncode(llarp_buffer_t* buf) const
{
(void)buf;
// TODO: implement me
return false;
}
bool
UpdateExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
(void)k;
(void)buf;
// TODO: implement me
return false;
}
bool
UpdateExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleUpdateExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,88 @@
#include <llarp/handlers/exit.hpp>
namespace llarp
{
namespace handlers
{
ExitEndpoint::ExitEndpoint(const std::string &name, llarp_router *r)
: TunEndpoint(name, r), m_Name(name)
{
}
ExitEndpoint::~ExitEndpoint()
{
}
bool
ExitEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "exit")
{
// TODO: implement me
return true;
}
if(k == "exit-whitelist")
{
// add exit policy whitelist rule
// TODO: implement me
return true;
}
if(k == "exit-blacklist")
{
// add exit policy blacklist rule
// TODO: implement me
return true;
}
return TunEndpoint::SetOption(k, v);
}
void
ExitEndpoint::FlushSend()
{
m_UserToNetworkPktQueue.Process([&](net::IPv4Packet &pkt) {
// find pubkey for addr
auto itr = m_AddrsToPubKey.find(pkt.dst());
if(itr == m_AddrsToPubKey.end())
{
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
return true;
}
pkt.UpdateIPv4PacketOnSrc();
auto range = m_ActiveExits.equal_range(itr->second);
auto exit_itr = range.first;
while(exit_itr != range.second)
{
if(exit_itr->second.SendInboundTraffic(pkt.Buffer()))
return true;
++exit_itr;
}
// dropped
llarp::LogWarn(Name(), " dropped traffic to ", itr->second);
return true;
});
}
std::string
ExitEndpoint::Name() const
{
return m_Name;
}
void
ExitEndpoint::Tick(llarp_time_t now)
{
auto itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
if(itr->second.IsExpired(now))
{
itr = m_ActiveExits.erase(itr);
}
else
++itr;
}
// call parent
TunEndpoint::Tick(now);
}
} // namespace handlers
} // namespace llarp

@ -37,14 +37,6 @@ namespace llarp
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "nameresolver")
{
// we probably can set the property since the config will load before
// the relay is set up
// strncpy(tunif.ifname, v.c_str(), sizeof(tunif.ifname) - 1);
llarp::LogInfo(Name() + " would be setting DNS resolver to ", v);
return true;
}
if(k == "local-dns")
{
std::string resolverAddr = v;

@ -531,9 +531,9 @@ namespace llarp
}
bool
Path::SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r)
Path::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{
msg->S = m_SequenceNum++;
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
@ -658,5 +658,65 @@ namespace llarp
return true;
}
bool
Path::HandleCloseExitMessage(const llarp::routing::CloseExitMessage* msg,
llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
Path::HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
Path::HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage* msg,
llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
Path::HandleRejectExitMessage(const llarp::routing::RejectExitMessage* msg,
llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
Path::HandleGrantExitMessage(const llarp::routing::GrantExitMessage* msg,
llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
Path::HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
} // namespace path
} // namespace llarp

@ -121,6 +121,7 @@ llarp_router::HandleLinkSessionEstablished(llarp::RouterContact rc)
llarp_router::llarp_router()
: ready(false)
, paths(this)
, exitContext(this)
, dht(llarp_dht_context_new(this))
, inbound_link_msg_parser(this)
, hiddenServiceContext(this)
@ -506,13 +507,14 @@ llarp_router::Tick()
dht->impl.Explore(explore);
}
paths.BuildPaths(now);
hiddenServiceContext.Tick();
hiddenServiceContext.Tick(now);
}
if(NumberOfConnectedRouters() < minConnectedRouters)
{
ConnectToRandomRouters(minConnectedRouters);
}
paths.TickPaths(now);
exitContext.Tick(now);
}
void
@ -794,7 +796,11 @@ llarp_router::Run()
if(IBLinksStarted > 0)
{
// initialize as service node
InitServiceNode();
if(!InitServiceNode())
{
llarp::LogError("Failed to initialize service node");
return;
}
// immediate connect all for service node
uint64_t delay = llarp_randint() % 100;
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
@ -881,12 +887,13 @@ llarp_router::ShouldCreateDefaultHiddenService()
return false;
}
void
bool
llarp_router::InitServiceNode()
{
llarp::LogInfo("accepting transit traffic");
paths.AllowTransit();
llarp_dht_allow_transit(dht);
return exitContext.AddExitEndpoint("default-connectivity", exitConf);
}
void
@ -1190,6 +1197,10 @@ namespace llarp
{
self->defaultIfName = val;
}
if(!StrEq(key, "profiles"))
{
self->exitConf.insert(std::make_pair(key, val));
}
}
else if(StrEq(section, "api"))
{

@ -20,6 +20,7 @@
#include <llarp/service.hpp>
#include <llarp/establish_job.hpp>
#include <llarp/profiling.hpp>
#include <llarp/exit.hpp>
#include "crypto.hpp"
#include "fs.hpp"
@ -67,6 +68,7 @@ struct llarp_router
llarp_logic *logic;
llarp_crypto crypto;
llarp::path::PathContext paths;
llarp::exit::Context exitContext;
llarp::SecretKey identity;
llarp::SecretKey encryption;
llarp_threadpool *disk;
@ -97,6 +99,9 @@ struct llarp_router
std::string defaultIfAddr = "auto";
std::string defaultIfName = "auto";
/// default exit config
llarp::exit::Context::Config_t exitConf;
bool
CreateDefaultHiddenService();
@ -159,7 +164,8 @@ struct llarp_router
InitOutboundLink();
/// initialize us as a service node
void
/// return true on success
bool
InitServiceNode();
void

@ -60,6 +60,24 @@ namespace llarp
case 'H':
self->msg.reset(new service::ProtocolFrame());
break;
case 'I':
self->msg.reset(new TransferTrafficMessage());
break;
case 'G':
self->msg.reset(new GrantExitMessage());
break;
case 'J':
self->msg.reset(new RejectExitMessage());
break;
case 'O':
self->msg.reset(new ObtainExitMessage());
break;
case 'U':
self->msg.reset(new UpdateExitMessage());
break;
case 'C':
self->msg.reset(new CloseExitMessage());
break;
default:
llarp::LogError("invalid routing message id: ", *strbuf.cur);
}

@ -21,9 +21,8 @@ namespace llarp
}
void
Context::Tick()
Context::Tick(llarp_time_t now)
{
auto now = m_Router->Now();
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())
{

@ -51,7 +51,7 @@ namespace llarp
}
bool
TransitHop::SendRoutingMessage(llarp::routing::IMessage* msg,
TransitHop::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{
if(!IsEndpoint(r->pubkey()))
@ -149,6 +149,66 @@ namespace llarp
return false;
}
bool
TransitHop::HandleObtainExitMessage(
const llarp::routing::ObtainExitMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandleCloseExitMessage(
const llarp::routing::CloseExitMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandleUpdateExitMessage(
const llarp::routing::UpdateExitMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandleRejectExitMessage(
const llarp::routing::RejectExitMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandleGrantExitMessage(
const llarp::routing::GrantExitMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg, llarp_router* r)
{
// TODO: implement me
(void)msg;
(void)r;
return false;
}
bool
TransitHop::HandlePathTransferMessage(
const llarp::routing::PathTransferMessage* msg, llarp_router* r)

@ -0,0 +1,39 @@
#include <gtest/gtest.h>
#include <llarp/messages/exit.hpp>
using ObtainExitMessage = llarp::routing::ObtainExitMessage;
class ObtainExitTest : public ::testing::Test
{
public:
llarp_crypto crypto;
llarp::SecretKey alice;
ObtainExitTest()
{
llarp_crypto_init(&crypto);
}
~ObtainExitTest()
{
}
void
SetUp()
{
crypto.identity_keygen(alice);
}
};
TEST_F(ObtainExitTest, TestSignVerify)
{
ObtainExitMessage msg;
msg.Z.Zero();
msg.S = llarp_randint();
msg.T = llarp_randint();
ASSERT_TRUE(msg.Sign(&crypto, alice));
ASSERT_TRUE(msg.Verify(&crypto));
ASSERT_TRUE(msg.I == llarp::PubKey(llarp::seckey_topublic(alice)));
ASSERT_FALSE(msg.version != LLARP_PROTO_VERSION);
ASSERT_FALSE(msg.Z.IsZero());
};

@ -0,0 +1,53 @@
#include <gtest/gtest.h>
#include <llarp/messages/transfer_traffic.hpp>
using TransferTrafficMessage = llarp::routing::TransferTrafficMessage;
class TransferTrafficTest : public ::testing::Test
{
public:
llarp_crypto crypto;
llarp::SecretKey alice;
TransferTrafficTest()
{
llarp_crypto_init(&crypto);
}
~TransferTrafficTest()
{
}
void
SetUp()
{
crypto.identity_keygen(alice);
}
};
TEST_F(TransferTrafficTest, TestSignVerify)
{
TransferTrafficMessage msg;
msg.X.resize(1024);
msg.S = 100;
crypto.randbytes(msg.X.data(), 1024);
ASSERT_TRUE(msg.Sign(&crypto, alice));
ASSERT_FALSE(msg.Z.IsZero());
ASSERT_TRUE(msg.Verify(&crypto, llarp::seckey_topublic(alice)));
};
TEST_F(TransferTrafficTest, TestPutBufferOverflow)
{
TransferTrafficMessage msg;
byte_t tmp[llarp::routing::MaxExitMTU * 2] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
ASSERT_FALSE(msg.PutBuffer(buf));
};
TEST_F(TransferTrafficTest, TestPutBuffer)
{
TransferTrafficMessage msg;
byte_t tmp[llarp::routing::MaxExitMTU] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
ASSERT_TRUE(msg.PutBuffer(buf));
};
Loading…
Cancel
Save