mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-15 12:13:24 +00:00
Prefiguring, deprecation
- TunEndpoint and LocalEndpoint prefiguring - Fully removed service::Address and all uses of AddressVariant_t in favor of the improved NetworkAddress type - Fully removed exit/* and most of service/*
This commit is contained in:
parent
791155d1c9
commit
078d0dfc23
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "lokinet_context.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "lokinet_export.h"
|
||||
#include "export.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lokinet_context.h"
|
||||
#include "lokinet_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// poll many sockets for activity
|
||||
/// each pollfd.fd should be set to the socket id
|
||||
/// returns 0 on sucess
|
||||
int EXPORT lokinet_poll(struct pollfd* poll, nfds_t numsockets, struct lokinet_context* ctx);
|
||||
|
||||
/// close a udp socket or a stream socket by its id
|
||||
void EXPORT lokinet_close_socket(int id, struct lokinet_context* ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "lokinet_export.h"
|
||||
#include "export.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "lokinet_context.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "lokinet_context.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "lokinet_context.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
@ -30,17 +30,10 @@ lokinet_add_library(lokinet-core-utils
|
||||
handlers/remote.cpp
|
||||
handlers/tun.cpp
|
||||
|
||||
# deprecated for handlers/{endpoint,remote}.cpp
|
||||
# exit/handler.cpp
|
||||
# exit/endpoint.cpp
|
||||
# service/handler.cpp # link/ exit/
|
||||
# service/endpoint.cpp
|
||||
|
||||
service/identity.cpp
|
||||
service/info.cpp
|
||||
service/intro.cpp # path
|
||||
service/intro_set.cpp
|
||||
service/lns_tracker.cpp
|
||||
service/name.cpp
|
||||
|
||||
vpn/egres_packet_router.cpp
|
||||
@ -50,19 +43,13 @@ lokinet_add_library(lokinet-core
|
||||
context.cpp
|
||||
|
||||
consensus/reachability_testing.cpp
|
||||
|
||||
# handlers/tun.cpp
|
||||
|
||||
link/link_manager.cpp
|
||||
|
||||
router/router.cpp
|
||||
router/route_poker.cpp
|
||||
|
||||
# service/async_key_exchange.cpp
|
||||
service/types.cpp
|
||||
service/endpoint_state.cpp
|
||||
service/protocol.cpp
|
||||
service/session.cpp
|
||||
|
||||
session/outbound_session.cpp
|
||||
session/inbound_session.cpp
|
||||
@ -119,7 +106,6 @@ lokinet_add_library(lokinet-time-place
|
||||
router_id.cpp
|
||||
router_version.cpp # to be deleted shortly
|
||||
|
||||
service/address.cpp
|
||||
service/tag.cpp
|
||||
)
|
||||
|
||||
|
@ -59,6 +59,11 @@ namespace llarp
|
||||
bool operator==(const NetworkAddress& other) const;
|
||||
bool operator!=(const NetworkAddress& other) const;
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return _pubkey.is_zero() and _tld.empty();
|
||||
}
|
||||
|
||||
// Will throw invalid_argument with bad input. Assumes that the network address terminates in either '.loki'
|
||||
// or '.snode'
|
||||
static std::optional<NetworkAddress> from_network_addr(std::string arg);
|
||||
@ -78,7 +83,7 @@ namespace llarp
|
||||
return _pubkey;
|
||||
}
|
||||
|
||||
PubKey pubkey()
|
||||
PubKey& pubkey()
|
||||
{
|
||||
return _pubkey;
|
||||
}
|
||||
|
@ -78,6 +78,11 @@ namespace llarp
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_remote(const net_addr_t& remote) const
|
||||
{
|
||||
return _remote_to_local.contains(remote);
|
||||
}
|
||||
|
||||
void unmap(const net_addr_t& remote)
|
||||
{
|
||||
auto name = remote.name();
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
#include <llarp/address/address.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/protocol.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/service/tag.hpp>
|
||||
#include <llarp/util/str.hpp>
|
||||
#include <llarp/util/thread/threading.hpp>
|
||||
@ -20,11 +19,6 @@
|
||||
namespace llarp
|
||||
{
|
||||
struct Router;
|
||||
|
||||
namespace service
|
||||
{
|
||||
struct Endpoint;
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
namespace llarp::auth
|
||||
@ -52,14 +46,6 @@ namespace llarp::auth
|
||||
{
|
||||
return _router;
|
||||
}
|
||||
|
||||
/// asynchronously determine if we accept new convotag from remote service, call hook with
|
||||
/// result later
|
||||
virtual void authenticate_async(
|
||||
std::shared_ptr<service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook) = 0;
|
||||
|
||||
/// return true if we are asynchronously processing authentication on this sessiontag
|
||||
virtual bool auth_async_pending(service::SessionTag tag) const = 0;
|
||||
};
|
||||
|
||||
struct SessionAuthPolicy final : public AuthPolicy, public std::enable_shared_from_this<SessionAuthPolicy>
|
||||
@ -101,11 +87,6 @@ namespace llarp::auth
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
void authenticate_async(
|
||||
std::shared_ptr<service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook) override;
|
||||
|
||||
bool auth_async_pending(service::SessionTag tag) const override;
|
||||
};
|
||||
|
||||
struct FileAuthPolicy final : public AuthPolicy, public std::enable_shared_from_this<FileAuthPolicy>
|
||||
@ -124,11 +105,6 @@ namespace llarp::auth
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
void authenticate_async(
|
||||
std::shared_ptr<service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook) override;
|
||||
|
||||
bool auth_async_pending(service::SessionTag tag) const override;
|
||||
|
||||
private:
|
||||
const std::set<fs::path> _files;
|
||||
const AuthFileType _type;
|
||||
@ -147,10 +123,9 @@ namespace llarp::auth
|
||||
Router& r,
|
||||
std::string url,
|
||||
std::string method,
|
||||
std::unordered_set<llarp::service::Address> addr_whitelist,
|
||||
std::unordered_set<NetworkAddress> addr_whitelist,
|
||||
std::unordered_set<std::string> token_whitelist,
|
||||
std::shared_ptr<oxenmq::OxenMQ> lmq,
|
||||
std::shared_ptr<service::Endpoint> endpoint);
|
||||
std::shared_ptr<oxenmq::OxenMQ> lmq);
|
||||
|
||||
~RPCAuthPolicy() override = default;
|
||||
|
||||
@ -166,19 +141,13 @@ namespace llarp::auth
|
||||
|
||||
void start();
|
||||
|
||||
void authenticate_async(
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook) override;
|
||||
|
||||
bool auth_async_pending(service::SessionTag tag) const override;
|
||||
|
||||
private:
|
||||
const std::string _url;
|
||||
const std::string _method;
|
||||
const std::unordered_set<llarp::service::Address> _whitelist;
|
||||
const std::unordered_set<NetworkAddress> _whitelist;
|
||||
const std::unordered_set<std::string> _static_tokens;
|
||||
|
||||
std::shared_ptr<oxenmq::OxenMQ> _omq;
|
||||
std::shared_ptr<service::Endpoint> _ep;
|
||||
std::optional<oxenmq::ConnectionID> _omq_conn;
|
||||
std::unordered_set<service::SessionTag> _pending_sessions;
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "auth.hpp"
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/service/protocol.hpp>
|
||||
#include <llarp/util/str.hpp>
|
||||
|
||||
namespace llarp::auth
|
||||
@ -42,43 +41,4 @@ namespace llarp::auth
|
||||
}
|
||||
}
|
||||
|
||||
void FileAuthPolicy::authenticate_async(
|
||||
std::shared_ptr<service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook)
|
||||
{
|
||||
auto reply = router().loop()->make_caller([tag = msg->tag, hook, self = shared_from_this()](AuthResult result) {
|
||||
{
|
||||
util::Lock _lock{self->_m};
|
||||
self->_pending.erase(tag);
|
||||
}
|
||||
hook(result.reason, result.code == AuthCode::ACCEPTED);
|
||||
});
|
||||
{
|
||||
util::Lock _lock{_m};
|
||||
_pending.emplace(msg->tag);
|
||||
}
|
||||
if (msg->proto == service::ProtocolType::Auth)
|
||||
{
|
||||
router().queue_disk_io(
|
||||
[self = shared_from_this(),
|
||||
auth = AuthInfo{std::string{reinterpret_cast<const char*>(msg->payload.data()), msg->payload.size()}},
|
||||
reply]() {
|
||||
try
|
||||
{
|
||||
reply(self->check_files(auth));
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
reply(AuthResult{AuthCode::FAILED, ex.what()});
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
reply(AuthResult{AuthCode::REJECTED, "protocol error"});
|
||||
}
|
||||
|
||||
bool FileAuthPolicy::auth_async_pending(service::SessionTag tag) const
|
||||
{
|
||||
util::Lock _lock{_m};
|
||||
return _pending.count(tag);
|
||||
}
|
||||
} // namespace llarp::auth
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "auth.hpp"
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/service/endpoint.hpp>
|
||||
|
||||
namespace llarp::auth
|
||||
{
|
||||
@ -11,17 +10,15 @@ namespace llarp::auth
|
||||
Router& r,
|
||||
std::string url,
|
||||
std::string method,
|
||||
std::unordered_set<llarp::service::Address> whitelist_addrs,
|
||||
std::unordered_set<NetworkAddress> whitelist_addrs,
|
||||
std::unordered_set<std::string> whitelist_tokens,
|
||||
std::shared_ptr<oxenmq::OxenMQ> lmq,
|
||||
std::shared_ptr<service::Endpoint> endpoint)
|
||||
std::shared_ptr<oxenmq::OxenMQ> lmq)
|
||||
: AuthPolicy{r},
|
||||
_url{std::move(url)},
|
||||
_method{std::move(method)},
|
||||
_whitelist{std::move(whitelist_addrs)},
|
||||
_static_tokens{std::move(whitelist_tokens)},
|
||||
_omq{std::move(lmq)},
|
||||
_ep{std::move(endpoint)}
|
||||
_omq{std::move(lmq)}
|
||||
{}
|
||||
|
||||
void RPCAuthPolicy::start()
|
||||
@ -41,86 +38,4 @@ namespace llarp::auth
|
||||
});
|
||||
}
|
||||
|
||||
bool RPCAuthPolicy::auth_async_pending(service::SessionTag tag) const
|
||||
{
|
||||
return _pending_sessions.count(tag) > 0;
|
||||
}
|
||||
|
||||
void RPCAuthPolicy::authenticate_async(
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook)
|
||||
{
|
||||
service::SessionTag tag = msg->tag;
|
||||
_pending_sessions.insert(tag);
|
||||
const auto from = msg->sender.address();
|
||||
auto reply = _ep->loop()->make_caller([this, tag, hook](std::string code, bool success) {
|
||||
_pending_sessions.erase(tag);
|
||||
hook(code, success);
|
||||
});
|
||||
if (_whitelist.count(from))
|
||||
{
|
||||
// explicitly whitelisted source
|
||||
reply("explicitly whitelisted", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->proto != llarp::service::ProtocolType::Auth)
|
||||
{
|
||||
// not an auth message, reject
|
||||
reply("protocol error", false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string payload{(char*)msg->payload.data(), msg->payload.size()};
|
||||
|
||||
if (_static_tokens.count(payload))
|
||||
{
|
||||
reply("explicitly whitelisted", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (not _omq_conn.has_value())
|
||||
{
|
||||
if (_static_tokens.empty())
|
||||
{
|
||||
// we don't have a connection to the backend so it's failed
|
||||
reply("remote has no connection to auth backend", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// static auth mode
|
||||
reply("access not permitted", true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const auto authinfo = msg->encode_auth_info();
|
||||
std::string_view metainfo{authinfo.data(), authinfo.size()};
|
||||
// call method with 2 parameters: metainfo and userdata
|
||||
_omq->request(
|
||||
*_omq_conn,
|
||||
_method,
|
||||
[self = shared_from_this(), reply = std::move(reply)](bool success, std::vector<std::string> data) {
|
||||
AuthResult result{AuthCode::FAILED, "no reason given"};
|
||||
|
||||
if (success and not data.empty())
|
||||
{
|
||||
if (const auto maybe = parse_auth_code(data[0]))
|
||||
{
|
||||
result.code = *maybe;
|
||||
}
|
||||
if (result.code == AuthCode::ACCEPTED)
|
||||
{
|
||||
result.reason = "OK";
|
||||
}
|
||||
if (data.size() > 1)
|
||||
{
|
||||
result.reason = data[1];
|
||||
}
|
||||
}
|
||||
|
||||
reply(result.reason, success);
|
||||
},
|
||||
metainfo,
|
||||
payload);
|
||||
}
|
||||
} // namespace llarp::auth
|
||||
|
@ -824,7 +824,7 @@ namespace llarp
|
||||
|
||||
if (auto maybe_netaddr = NetworkAddress::from_network_addr(*arg))
|
||||
{
|
||||
_persisting_addrs.emplace(std::move(*maybe_netaddr), std::move(addr));
|
||||
_reserved_local_addrs.emplace(std::move(*maybe_netaddr), std::move(addr));
|
||||
}
|
||||
else
|
||||
log::warning(logcat, "{}: {}", addrmap_errorstr, *arg);
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <llarp/net/net_int.hpp>
|
||||
#include <llarp/net/traffic_policy.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/util/fs.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
#include <llarp/util/str.hpp>
|
||||
@ -141,11 +140,9 @@ namespace llarp
|
||||
|
||||
/* TESTNET: Under modification */
|
||||
|
||||
// Contents of this file are read directly into ::_reserved_local_addrs
|
||||
std::optional<fs::path> addr_map_persist_file;
|
||||
|
||||
// Pass to TunEndpoint -- combine with _reserved_local_addrs
|
||||
std::unordered_map<NetworkAddress, oxen::quic::Address> _persisting_addrs;
|
||||
|
||||
// the only member that refers to an actual interface
|
||||
std::optional<std::string> _if_name;
|
||||
|
||||
@ -158,8 +155,7 @@ namespace llarp
|
||||
|
||||
// Remote exit or hidden service addresses mapped to fixed local IP addresses
|
||||
// TODO:
|
||||
// - pass to TunEndpoint
|
||||
// - create separate "reserved_ips" mapping or load directly into TunEndpoint mapping (probably better)
|
||||
// - pass to TunEndpoint, load directly into TunEndpoint mapping
|
||||
// - when a session is created, check here when assigning IP's
|
||||
std::unordered_map<NetworkAddress, oxen::quic::Address> _reserved_local_addrs;
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <llarp/dns/srv_data.hpp>
|
||||
#include <llarp/ev/loop.hpp>
|
||||
#include <llarp/link/tunnel.hpp>
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/tag.hpp>
|
||||
#include <llarp/service/types.hpp>
|
||||
#include <llarp/session/map.hpp>
|
||||
@ -38,7 +37,7 @@ namespace llarp
|
||||
std::unordered_set<dns::SRVData> _srv_records;
|
||||
|
||||
public:
|
||||
bool _publish_introset{true};
|
||||
bool should_publish_introset{true};
|
||||
|
||||
// TODO: replace with session_map type
|
||||
// std::unordered_map<service::SessionTag, RouterID> _session_lookup;
|
||||
|
@ -1,10 +0,0 @@
|
||||
#include "endpoint.hpp"
|
||||
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/service/handler.hpp>
|
||||
|
||||
namespace llarp::exit
|
||||
{
|
||||
//
|
||||
} // namespace llarp::exit
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/address/ip_range.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/service/types.hpp>
|
||||
#include <llarp/util/time.hpp>
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace llarp::exit
|
||||
{
|
||||
/**
|
||||
TONUKE: all of this
|
||||
*/
|
||||
|
||||
/** This class is the counterpart to service::Endpoint. While service::Endpoint manages hidden
|
||||
services ran locally, exit::Endpoint manages locally operated client exit nodes
|
||||
*/
|
||||
struct Endpoint /* final */ : public path::PathHandler,
|
||||
/* public EndpointBase, */
|
||||
public std::enable_shared_from_this<Endpoint>
|
||||
{
|
||||
std::shared_ptr<path::PathHandler> get_self() override
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::weak_ptr<path::PathHandler> get_weak() override
|
||||
{
|
||||
return weak_from_this();
|
||||
}
|
||||
|
||||
std::unordered_map<IPRange, service::Address> _exit_map;
|
||||
std::set<IPRange> _owned_ranges;
|
||||
};
|
||||
} // namespace llarp::exit
|
@ -1,15 +0,0 @@
|
||||
#include "handler.hpp"
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace llarp::exit
|
||||
{
|
||||
Handler::Handler(std::string /* name */, Router& /* r */) /* : handlers::RemoteHandler{std::move(name), r} */
|
||||
{}
|
||||
|
||||
void Handler::_configure()
|
||||
{}
|
||||
} // namespace llarp::exit
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// #include <llarp/dns/server.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/handlers/remote.hpp>
|
||||
#include <llarp/session/session.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llarp::exit
|
||||
{
|
||||
/** This class is the counterpart to service::Handler. While service::Handler manages sessions
|
||||
to remote hidden services, exit::Handler manages sessions to remote exit nodes
|
||||
*/
|
||||
struct Handler final : /* public handlers::RemoteHandler, */ public std::enable_shared_from_this<Handler>
|
||||
{
|
||||
private:
|
||||
void _configure();
|
||||
|
||||
public:
|
||||
Handler(std::string name, Router& r);
|
||||
~Handler() = default;
|
||||
};
|
||||
} // namespace llarp::exit
|
@ -4,7 +4,6 @@
|
||||
#include <llarp/dns/server.hpp>
|
||||
#include <llarp/ev/loop.hpp>
|
||||
#include <llarp/net/net.hpp>
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/identity.hpp>
|
||||
#include <llarp/service/name.hpp>
|
||||
#include <llarp/session/session.hpp>
|
||||
@ -56,7 +55,7 @@ namespace llarp::handlers
|
||||
|
||||
virtual bool supports_ipv6() const = 0;
|
||||
|
||||
virtual bool configure(const NetworkConfig& conf, const DnsConfig& dnsConf) = 0;
|
||||
virtual bool configure() = 0;
|
||||
|
||||
virtual bool setup_networking() = 0;
|
||||
|
||||
|
@ -2,20 +2,23 @@
|
||||
|
||||
namespace llarp::handlers
|
||||
{
|
||||
static auto logcat = log::Cat("Null");
|
||||
static auto logcat = log::Cat("EmbeddedEndpoint");
|
||||
|
||||
EmbeddedEndpoint::EmbeddedEndpoint(Router& r)
|
||||
: BaseHandler{r}, _packet_router{new vpn::EgresPacketRouter{[](AddressVariant_t from, IPPacket pkt) {
|
||||
var::visit(
|
||||
[&pkt](AddressVariant_t&& from) {
|
||||
log::error(logcat, "Unhandled traffic from {} (pkt size:{}B)", from, pkt.size());
|
||||
},
|
||||
from);
|
||||
: BaseHandler{r}, _packet_router{new vpn::EgresPacketRouter{[](NetworkAddress from, IPPacket pkt) {
|
||||
(void)from;
|
||||
(void)pkt;
|
||||
// TODO: something smart here!
|
||||
}}}
|
||||
{
|
||||
// r->loop()->add_ticker([this] { Pump(Now()); });
|
||||
}
|
||||
|
||||
bool EmbeddedEndpoint::configure()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmbeddedEndpoint::handle_inbound_packet(
|
||||
const service::SessionTag tag, const llarp_buffer_t& buf, service::ProtocolType t, uint64_t)
|
||||
{
|
||||
|
@ -51,12 +51,7 @@ namespace llarp::handlers
|
||||
}
|
||||
|
||||
// TODO: this
|
||||
bool configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override
|
||||
{
|
||||
(void)conf;
|
||||
(void)dnsConf;
|
||||
return true;
|
||||
}
|
||||
bool configure() override;
|
||||
|
||||
bool handle_inbound_packet(
|
||||
const service::SessionTag tag, const llarp_buffer_t& buf, service::ProtocolType t, uint64_t) override;
|
||||
|
@ -48,27 +48,30 @@ namespace llarp::handlers
|
||||
void LocalEndpoint::configure()
|
||||
{
|
||||
// auto _dns_config = _router.config()->dns;
|
||||
auto _net_config = _router.config()->network;
|
||||
auto net_config = _router.config()->network;
|
||||
|
||||
if (net_config.is_reachable)
|
||||
should_publish_introset = true;
|
||||
|
||||
_is_exit_node = _router.is_exit_node();
|
||||
_is_snode_service = _router.is_service_node();
|
||||
|
||||
if (_is_exit_node)
|
||||
{
|
||||
if (not _net_config._routed_ranges.empty())
|
||||
if (not net_config._routed_ranges.empty())
|
||||
{
|
||||
_routed_ranges.merge(_net_config._routed_ranges);
|
||||
_routed_ranges.merge(net_config._routed_ranges);
|
||||
_local_introset._routed_ranges = _routed_ranges;
|
||||
}
|
||||
|
||||
_exit_policy = _net_config.traffic_policy;
|
||||
_exit_policy = net_config.traffic_policy;
|
||||
_local_introset.exit_policy = _exit_policy;
|
||||
}
|
||||
|
||||
_if_name = *_net_config._if_name;
|
||||
_local_range = *_net_config._local_ip_range;
|
||||
_local_addr = *_net_config._local_addr;
|
||||
_local_ip = *_net_config._local_ip;
|
||||
_if_name = *net_config._if_name;
|
||||
_local_range = *net_config._local_ip_range;
|
||||
_local_addr = *net_config._local_addr;
|
||||
_local_ip = *net_config._local_ip;
|
||||
|
||||
_is_v4 = _local_range.is_ipv4();
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/address/ip_range.hpp>
|
||||
#include <llarp/address/map.hpp>
|
||||
#include <llarp/auth/auth.hpp>
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/service/intro_set.hpp>
|
||||
#include <llarp/session/session.hpp>
|
||||
|
||||
namespace llarp
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <llarp/nodedb.hpp>
|
||||
#include <llarp/router/route_poker.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/service/endpoint_state.hpp>
|
||||
#include <llarp/service/name.hpp>
|
||||
#include <llarp/service/types.hpp>
|
||||
#include <llarp/util/str.hpp>
|
||||
@ -139,10 +138,12 @@ namespace llarp::handlers
|
||||
|
||||
void TunEndpoint::setup_dns()
|
||||
{
|
||||
auto& dns_config = _router.config()->dns;
|
||||
const auto& info = get_vpn_interface()->Info();
|
||||
if (_dns_config.raw)
|
||||
|
||||
if (dns_config.raw)
|
||||
{
|
||||
auto dns = std::make_shared<TunDNS>(this, _dns_config);
|
||||
auto dns = std::make_shared<TunDNS>(this, dns_config);
|
||||
_dns = dns;
|
||||
|
||||
_packet_router->add_udp_handler(uint16_t{53}, [this, dns](UDPPacket pkt) {
|
||||
@ -164,12 +165,12 @@ namespace llarp::handlers
|
||||
});
|
||||
}
|
||||
else
|
||||
_dns = std::make_shared<dns::Server>(router().loop(), _dns_config, info.index);
|
||||
_dns = std::make_shared<dns::Server>(router().loop(), dns_config, info.index);
|
||||
|
||||
_dns->add_resolver(weak_from_this());
|
||||
_dns->start();
|
||||
|
||||
if (_dns_config.raw)
|
||||
if (dns_config.raw)
|
||||
{
|
||||
if (auto vpn = router().vpn_platform())
|
||||
{
|
||||
@ -260,31 +261,22 @@ namespace llarp::handlers
|
||||
}
|
||||
}
|
||||
|
||||
bool TunEndpoint::configure(const NetworkConfig& conf, const DnsConfig& dnsConf)
|
||||
bool TunEndpoint::configure()
|
||||
{
|
||||
// if (conf.is_reachable)
|
||||
// {
|
||||
// _publish_introset = true;
|
||||
// log::info(logcat, "TunEndpoint setting to be reachable by default");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _publish_introset = false;
|
||||
// log::info(logcat, "TunEndpoint setting to be not reachable by default");
|
||||
// }
|
||||
auto& net_conf = _router.config()->network;
|
||||
|
||||
if (conf.auth_type == auth::AuthType::FILE)
|
||||
if (net_conf.auth_type == auth::AuthType::FILE)
|
||||
{
|
||||
// _auth_policy = auth::make_auth_policy<auth::FileAuthPolicy>(router(),
|
||||
// conf.auth_files, conf.auth_file_type);
|
||||
}
|
||||
else if (conf.auth_type != auth::AuthType::NONE)
|
||||
else if (net_conf.auth_type != auth::AuthType::NONE)
|
||||
{
|
||||
std::string url, method;
|
||||
if (conf.auth_url.has_value() and conf.auth_method.has_value())
|
||||
if (net_conf.auth_url.has_value() and net_conf.auth_method.has_value())
|
||||
{
|
||||
url = *conf.auth_url;
|
||||
method = *conf.auth_method;
|
||||
url = *net_conf.auth_url;
|
||||
method = *net_conf.auth_method;
|
||||
}
|
||||
// TODO:
|
||||
// auto auth = auth::make_auth_policy<auth::RPCAuthPolicy>(
|
||||
@ -299,155 +291,32 @@ namespace llarp::handlers
|
||||
// _auth_policy = std::move(auth);
|
||||
}
|
||||
|
||||
_dns_config = dnsConf;
|
||||
_traffic_policy = conf.traffic_policy;
|
||||
_traffic_policy = net_conf.traffic_policy;
|
||||
|
||||
_base_ipv6_range = conf._base_ipv6_range;
|
||||
_base_ipv6_range = net_conf._base_ipv6_range;
|
||||
|
||||
if (conf.path_alignment_timeout)
|
||||
if (net_conf.path_alignment_timeout)
|
||||
{
|
||||
_path_alignment_timeout = *conf.path_alignment_timeout;
|
||||
}
|
||||
else
|
||||
_path_alignment_timeout = service::DEFAULT_PATH_ALIGN_TIMEOUT;
|
||||
if (is_service_node())
|
||||
throw std::runtime_error{"Service nodes cannot specify path alignment timeout!"};
|
||||
|
||||
for (const auto& item : conf._reserved_local_addrs)
|
||||
{
|
||||
(void)item;
|
||||
// if (not map_address(item.second, item.first, false))
|
||||
// return false;
|
||||
_path_alignment_timeout = *net_conf.path_alignment_timeout;
|
||||
}
|
||||
|
||||
_if_name = *conf._if_name;
|
||||
_local_range = *conf._local_ip_range;
|
||||
_local_addr = *conf._local_addr;
|
||||
_local_ip = *conf._local_ip;
|
||||
_if_name = *net_conf._if_name;
|
||||
_local_range = *net_conf._local_ip_range;
|
||||
_local_addr = *net_conf._local_addr;
|
||||
_local_ip = *net_conf._local_ip;
|
||||
|
||||
_use_v6 = not _local_range.is_ipv4();
|
||||
|
||||
_persisting_addr_file = conf.addr_map_persist_file;
|
||||
_persisting_addr_file = net_conf.addr_map_persist_file;
|
||||
|
||||
if (conf.addr_map_persist_file and not conf._persisting_addrs.empty())
|
||||
if (not net_conf._reserved_local_addrs.empty())
|
||||
{
|
||||
}
|
||||
|
||||
if (_persisting_addr_file)
|
||||
{
|
||||
const auto& file = *_persisting_addr_file;
|
||||
|
||||
if (fs::exists(file))
|
||||
for (auto& [remote, local] : net_conf._reserved_local_addrs)
|
||||
{
|
||||
bool load_file = true;
|
||||
{
|
||||
constexpr auto LastModifiedWindow = 1min;
|
||||
const auto lastmodified = fs::last_write_time(file);
|
||||
const auto now = decltype(lastmodified)::clock::now();
|
||||
|
||||
if (now < lastmodified or now - lastmodified > LastModifiedWindow)
|
||||
{
|
||||
load_file = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char> data;
|
||||
|
||||
if (auto maybe = util::OpenFileStream<fs::ifstream>(file, std::ios_base::binary); maybe and load_file)
|
||||
{
|
||||
log::info(logcat, "{} loading persisting address map file from path:{}", name(), file);
|
||||
|
||||
maybe->seekg(0, std::ios_base::end);
|
||||
const size_t len = maybe->tellg();
|
||||
|
||||
maybe->seekg(0, std::ios_base::beg);
|
||||
data.resize(len);
|
||||
|
||||
log::debug(logcat, "{} reading {}B", name(), len);
|
||||
|
||||
maybe->read(data.data(), data.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto err = "{} could not load persisting address map file from path:{} --"_format(name(), file);
|
||||
|
||||
log::info(logcat, "{} {}", err, load_file ? "NOT FOUND" : "STALE");
|
||||
|
||||
if (load_file)
|
||||
{
|
||||
log::info(logcat, "{} NOT FOUND", err);
|
||||
}
|
||||
else
|
||||
log::info(logcat, "{} STALE", err);
|
||||
}
|
||||
if (not data.empty())
|
||||
{
|
||||
std::string_view bdata{data.data(), data.size()};
|
||||
|
||||
log::trace(logcat, "{} parsing address map data: {}", name(), bdata);
|
||||
|
||||
const auto parsed = oxenc::bt_deserialize<oxenc::bt_dict>(bdata);
|
||||
|
||||
for (const auto& [key, value] : parsed)
|
||||
{
|
||||
ip ip{};
|
||||
|
||||
// if (not ip.FromString(key))
|
||||
// {
|
||||
// log::warning(logcat, "{} malformed IP in addr map data: {}", name(), key);
|
||||
// continue;
|
||||
// }
|
||||
if (_local_ip == ip)
|
||||
continue;
|
||||
if (not _local_range.contains(ip))
|
||||
{
|
||||
// log::warning(logcat, "{} out of range IP in addr map data", name(), ip);
|
||||
continue;
|
||||
}
|
||||
|
||||
AddressVariant_t addr;
|
||||
|
||||
if (const auto* str = std::get_if<std::string>(&value))
|
||||
{
|
||||
if (auto maybe = parse_address(*str))
|
||||
{
|
||||
addr = *maybe;
|
||||
}
|
||||
else
|
||||
{
|
||||
log::warning(logcat, "{} invalid address in addr map: {}", name(), *str);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log::warning(logcat, "{} invalid first entry in addr map: not a string!", name());
|
||||
continue;
|
||||
}
|
||||
if (const auto* loki = std::get_if<service::Address>(&addr))
|
||||
{
|
||||
_ip_to_addr.emplace(ip, loki->data());
|
||||
_addr_to_ip.emplace(loki->data(), ip);
|
||||
_is_snode_map[*loki] = false;
|
||||
|
||||
log::info(logcat, "{} remapped {} to {}", name(), ip, *loki);
|
||||
}
|
||||
if (const auto* snode = std::get_if<RouterID>(&addr))
|
||||
{
|
||||
_ip_to_addr.emplace(ip, snode->data());
|
||||
_addr_to_ip.emplace(snode->data(), ip);
|
||||
_is_snode_map[*snode] = true;
|
||||
|
||||
log::info(logcat, "{} remapped {} to {}", name(), ip, *snode);
|
||||
}
|
||||
if (_next_ip < ip)
|
||||
_next_ip = ip;
|
||||
// make sure we dont unmap this guy
|
||||
mark_ip_active(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log::info(logcat, "{} skipping loading addr map at {} as it does not currently exist", name(), file);
|
||||
local_ip_mapping.insert_or_assign(local, remote);
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,11 +330,6 @@ namespace llarp::handlers
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TunEndpoint::has_local_ip(const ip& ip) const
|
||||
{
|
||||
return _ip_to_addr.find(ip) != _ip_to_addr.end();
|
||||
}
|
||||
|
||||
static bool is_random_snode(const dns::Message& msg)
|
||||
{
|
||||
return msg.questions[0].IsName("random.snode");
|
||||
@ -875,7 +739,7 @@ namespace llarp::handlers
|
||||
// FIXME: pass in which question it should be addressing
|
||||
bool TunEndpoint::should_hook_dns_message(const dns::Message& msg) const
|
||||
{
|
||||
llarp::service::Address addr;
|
||||
// llarp::service::Address addr;
|
||||
if (msg.questions.size() == 1)
|
||||
{
|
||||
/// hook every .loki
|
||||
@ -916,10 +780,14 @@ namespace llarp::handlers
|
||||
return setup_networking();
|
||||
}
|
||||
|
||||
bool TunEndpoint::is_snode() const
|
||||
bool TunEndpoint::is_service_node() const
|
||||
{
|
||||
// TODO : implement me
|
||||
return false;
|
||||
return _router.is_service_node();
|
||||
}
|
||||
|
||||
bool TunEndpoint::is_exit_node() const
|
||||
{
|
||||
return _router.is_exit_node();
|
||||
}
|
||||
|
||||
bool TunEndpoint::setup_tun()
|
||||
@ -929,12 +797,9 @@ namespace llarp::handlers
|
||||
log::info(logcat, "{} set {} to have address {}", name(), _if_name, _local_addr);
|
||||
// log::info(logcat, "{} allocated up to {} on range {}", name(), _max_ip, _local_range);
|
||||
|
||||
const service::Address ourAddr = _identity.pub.address();
|
||||
auto& local_netaddr = _identity.pub.address();
|
||||
|
||||
if (not map_address(ourAddr, get_if_addr(), false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
local_ip_mapping.insert_or_assign(get_if_addr(), local_netaddr);
|
||||
|
||||
vpn::InterfaceInfo info;
|
||||
info.addrs.emplace_back(_local_range);
|
||||
@ -990,7 +855,7 @@ namespace llarp::handlers
|
||||
log::info(logcat, "{} setting up DNS...", name());
|
||||
setup_dns();
|
||||
// loop()->call_soon([this]() { router().route_poker()->set_dns_mode(false); });
|
||||
return has_mapped_address(ourAddr);
|
||||
return has_mapped_address(local_netaddr);
|
||||
}
|
||||
|
||||
// std::unordered_map<std::string, std::string>
|
||||
@ -1229,8 +1094,10 @@ namespace llarp::handlers
|
||||
|
||||
bool TunEndpoint::is_allowing_traffic(const IPPacket& pkt) const
|
||||
{
|
||||
if (auto exitPolicy = get_traffic_policy())
|
||||
return exitPolicy->allow_ip_traffic(pkt);
|
||||
// if (auto exitPolicy = get_traffic_policy())
|
||||
// return exitPolicy->allow_ip_traffic(pkt);
|
||||
|
||||
(void)pkt;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1263,7 +1130,7 @@ namespace llarp::handlers
|
||||
if (t != service::ProtocolType::TrafficV4 && t != service::ProtocolType::TrafficV6
|
||||
&& t != service::ProtocolType::Exit)
|
||||
return false;
|
||||
std::variant<service::Address, RouterID> addr;
|
||||
// std::variant<service::Address, RouterID> addr;
|
||||
// if (auto maybe = GetEndpointWithConvoTag(tag))
|
||||
// {
|
||||
// addr = *maybe;
|
||||
@ -1344,9 +1211,8 @@ namespace llarp::handlers
|
||||
bool TunEndpoint::handle_write_ip_packet(const llarp_buffer_t& b, huint128_t src, huint128_t dst, uint64_t seqno)
|
||||
{
|
||||
ManagedBuffer buf(b);
|
||||
WritePacket write;
|
||||
write.seqno = seqno;
|
||||
auto& pkt = write.pkt;
|
||||
IPPacket pkt;
|
||||
|
||||
// load
|
||||
if (!pkt.load(buf.underlying.base))
|
||||
{
|
||||
@ -1362,6 +1228,7 @@ namespace llarp::handlers
|
||||
// }
|
||||
(void)src;
|
||||
(void)dst;
|
||||
(void)seqno;
|
||||
|
||||
// TODO: send this along but without a fucking huint182_t
|
||||
// m_NetworkToUserPktQueue.push(std::move(write));
|
||||
@ -1371,28 +1238,14 @@ namespace llarp::handlers
|
||||
return true;
|
||||
}
|
||||
|
||||
ip TunEndpoint::get_if_addr() const
|
||||
bool TunEndpoint::has_mapped_address(const NetworkAddress& addr) const
|
||||
{
|
||||
return _local_ip;
|
||||
return local_ip_mapping.has_remote(addr);
|
||||
}
|
||||
|
||||
bool TunEndpoint::is_ip_mapped(ip ip) const
|
||||
oxen::quic::Address TunEndpoint::get_if_addr() const
|
||||
{
|
||||
return _ip_to_addr.find(ip) != _ip_to_addr.end();
|
||||
}
|
||||
|
||||
void TunEndpoint::mark_ip_active(ip ip)
|
||||
{
|
||||
log::debug(logcat, "{} marking address {} active", name(), ip);
|
||||
// _ip_activity[ip] =
|
||||
// std::max(llarp::time_now_ms(), _ip_activity[ip]);
|
||||
}
|
||||
|
||||
void TunEndpoint::mark_ip_active_forever(ip ip)
|
||||
{
|
||||
log::debug(logcat, "{} marking address {} perpetually active", name(), ip);
|
||||
// _ip_activity[ip] =
|
||||
// std::numeric_limits<std::chrono::milliseconds>::max();
|
||||
return _local_addr;
|
||||
}
|
||||
|
||||
TunEndpoint::~TunEndpoint() = default;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "common.hpp"
|
||||
|
||||
#include <llarp/address/ip_packet.hpp>
|
||||
#include <llarp/address/map.hpp>
|
||||
#include <llarp/dns/server.hpp>
|
||||
#include <llarp/net/ip.hpp>
|
||||
#include <llarp/net/net.hpp>
|
||||
@ -71,7 +72,7 @@ namespace llarp::handlers
|
||||
// Reconfigures DNS servers and restarts libunbound with the new servers.
|
||||
void reconfigure_dns(std::vector<oxen::quic::Address> servers);
|
||||
|
||||
bool configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override;
|
||||
bool configure() override;
|
||||
|
||||
std::string get_if_name() const override;
|
||||
|
||||
@ -92,7 +93,9 @@ namespace llarp::handlers
|
||||
|
||||
bool stop();
|
||||
|
||||
bool is_snode() const;
|
||||
bool is_service_node() const;
|
||||
|
||||
bool is_exit_node() const;
|
||||
|
||||
/// set up tun interface, blocking
|
||||
bool setup_tun();
|
||||
@ -105,10 +108,10 @@ namespace llarp::handlers
|
||||
// return _dns;
|
||||
// };
|
||||
|
||||
/// overrides Endpoint
|
||||
/// overrides BaseHandler
|
||||
bool setup_networking() override;
|
||||
|
||||
/// overrides Endpoint
|
||||
/// overrides BaseHandler
|
||||
bool handle_inbound_packet(
|
||||
const service::SessionTag tag, const llarp_buffer_t& pkt, service::ProtocolType t, uint64_t seqno) override;
|
||||
|
||||
@ -118,24 +121,21 @@ namespace llarp::handlers
|
||||
/// we got a packet from the user
|
||||
void handle_user_packet(llarp::IPPacket pkt);
|
||||
|
||||
// TODO: change this to the new IP type after changing the member
|
||||
/// get the local interface's address
|
||||
ip get_if_addr() const /* override */;
|
||||
oxen::quic::Address get_if_addr() const;
|
||||
|
||||
/// we have an interface addr
|
||||
bool has_if_addr() const /* override */
|
||||
bool has_if_addr() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_local_ip(const ip& ip) const;
|
||||
|
||||
std::optional<net::TrafficPolicy> get_traffic_policy() const /* override */
|
||||
std::optional<net::TrafficPolicy> get_traffic_policy() const
|
||||
{
|
||||
return _traffic_policy;
|
||||
}
|
||||
|
||||
std::chrono::milliseconds get_path_alignment_timeout() const /* override */
|
||||
std::chrono::milliseconds get_path_alignment_timeout() const
|
||||
{
|
||||
return _path_alignment_timeout;
|
||||
}
|
||||
@ -145,10 +145,7 @@ namespace llarp::handlers
|
||||
/// returns true otherwise
|
||||
bool is_allowing_traffic(const IPPacket& pkt) const;
|
||||
|
||||
bool has_mapped_address(const AlignedBuffer<32>& addr) const
|
||||
{
|
||||
return _addr_to_ip.find(addr) != _addr_to_ip.end();
|
||||
}
|
||||
bool has_mapped_address(const NetworkAddress& addr) const;
|
||||
|
||||
protected:
|
||||
struct WritePacket
|
||||
@ -162,32 +159,7 @@ namespace llarp::handlers
|
||||
}
|
||||
};
|
||||
|
||||
/// return true if we have a remote loki address for this ip address
|
||||
bool is_ip_mapped(ip ipv4) const;
|
||||
|
||||
/// mark this address as active
|
||||
void mark_ip_active(ip ip);
|
||||
|
||||
/// mark this address as active forever
|
||||
void mark_ip_active_forever(ip ip);
|
||||
|
||||
/// flush writing ip packets to interface
|
||||
void flush_write();
|
||||
|
||||
// TONUKE: errythang buddy (move to handlers)
|
||||
/// maps ip to key (host byte order)
|
||||
std::unordered_map<ip, AlignedBuffer<32>> _ip_to_addr;
|
||||
|
||||
/// maps key to ip (host byte order)
|
||||
std::unordered_map<AlignedBuffer<32>, ip> _addr_to_ip;
|
||||
|
||||
/// maps key to true if key is a service node, maps key to false if key is
|
||||
/// a hidden service
|
||||
// TONUKE: this stupid POS
|
||||
std::unordered_map<AlignedBuffer<32>, bool> _is_snode_map;
|
||||
|
||||
/// maps ip address to an exit endpoint, useful when we have multiple exits on a range
|
||||
std::unordered_map<huint128_t, service::Address> _exit_to_ip;
|
||||
address_map<oxen::quic::Address, NetworkAddress> local_ip_mapping;
|
||||
|
||||
private:
|
||||
template <typename Addr_t, typename Endpoint_t>
|
||||
@ -212,12 +184,6 @@ namespace llarp::handlers
|
||||
/// dns subsystem for this endpoint
|
||||
std::shared_ptr<dns::Server> _dns;
|
||||
|
||||
DnsConfig _dns_config;
|
||||
|
||||
// TODO: change the IP's to the variant IP type in address/ip_range.hpp
|
||||
|
||||
/// maps ip address to timestamp last active
|
||||
std::unordered_map<huint128_t, std::chrono::milliseconds> _ip_activity;
|
||||
/// our local address and ip
|
||||
oxen::quic::Address _local_addr;
|
||||
ip _local_ip;
|
||||
@ -248,7 +214,7 @@ namespace llarp::handlers
|
||||
std::optional<net::TrafficPolicy> _traffic_policy = std::nullopt;
|
||||
|
||||
/// how long to wait for path alignment
|
||||
std::chrono::milliseconds _path_alignment_timeout;
|
||||
std::chrono::milliseconds _path_alignment_timeout{30s};
|
||||
|
||||
/// a file to load / store the ephemeral address map to
|
||||
std::optional<fs::path> _persisting_addr_file = std::nullopt;
|
||||
|
@ -523,7 +523,6 @@ namespace llarp
|
||||
void Router::init_api()
|
||||
{
|
||||
auto& net_config = _config->network;
|
||||
auto& dns_config = _config->dns;
|
||||
auto& type = net_config.endpoint_type;
|
||||
auto& key_file = net_config.keyfile;
|
||||
|
||||
@ -535,7 +534,7 @@ namespace llarp
|
||||
throw std::runtime_error{"Failed to construct API endpoint of type {}"_format(type)};
|
||||
|
||||
_api->load_key_file(key_file, *this);
|
||||
_api->configure(net_config, dns_config);
|
||||
_api->configure();
|
||||
}
|
||||
else
|
||||
throw std::runtime_error{"API endpoint of type {} does not exist"_format(type)};
|
||||
@ -632,10 +631,7 @@ namespace llarp
|
||||
// all snodes have Tun
|
||||
//
|
||||
// TODO: change this for snodes running hidden service
|
||||
if (not is_service_node())
|
||||
{
|
||||
init_api();
|
||||
}
|
||||
init_api();
|
||||
|
||||
if (not ensure_identity())
|
||||
throw std::runtime_error{"EnsureIdentity() failed"};
|
||||
|
@ -11,7 +11,8 @@ namespace llarp
|
||||
{
|
||||
static auto logcat = llarp::log::Cat("router_version");
|
||||
|
||||
RouterVersion::RouterVersion(const Version_t& router, uint64_t proto) : _version(router), _proto(proto)
|
||||
RouterVersion::RouterVersion(const std::array<uint16_t, 3>& router, uint64_t proto)
|
||||
: _version(router), _proto(proto)
|
||||
{}
|
||||
|
||||
bool RouterVersion::is_compatible_with(const RouterVersion& other) const
|
||||
|
@ -13,11 +13,9 @@ namespace llarp
|
||||
{
|
||||
struct RouterVersion
|
||||
{
|
||||
using Version_t = std::array<uint16_t, 3>;
|
||||
|
||||
RouterVersion() = default;
|
||||
|
||||
explicit RouterVersion(const Version_t& routerVersion, uint64_t protoVersion);
|
||||
explicit RouterVersion(const std::array<uint16_t, 3>& routerVersion, uint64_t protoVersion);
|
||||
|
||||
std::string bt_encode() const;
|
||||
|
||||
@ -51,7 +49,7 @@ namespace llarp
|
||||
}
|
||||
|
||||
private:
|
||||
Version_t _version = {{0, 0, 0}};
|
||||
std::array<uint16_t, 3> _version = {{0, 0, 0}};
|
||||
int64_t _proto = llarp::constants::proto_version;
|
||||
};
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/service/auth.hpp>
|
||||
#include <llarp/service/convotag.hpp>
|
||||
|
||||
#include <oxenmq/oxenmq.h>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
struct Endpoint;
|
||||
}
|
||||
|
||||
namespace llarp::rpc
|
||||
{
|
||||
struct EndpointAuthRPC : public llarp::service::IAuthPolicy, public std::enable_shared_from_this<EndpointAuthRPC>
|
||||
{
|
||||
using LMQ_ptr = std::shared_ptr<oxenmq::OxenMQ>;
|
||||
using Endpoint_ptr = std::shared_ptr<llarp::service::Endpoint>;
|
||||
using Whitelist_t = std::unordered_set<llarp::service::Address>;
|
||||
|
||||
explicit EndpointAuthRPC(
|
||||
std::string url,
|
||||
std::string method,
|
||||
Whitelist_t addr_whitelist,
|
||||
std::unordered_set<std::string> token_whitelist,
|
||||
LMQ_ptr lmq,
|
||||
Endpoint_ptr endpoint);
|
||||
|
||||
~EndpointAuthRPC() override = default;
|
||||
|
||||
void Start();
|
||||
|
||||
void authenticate_async(
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg, std::function<void(std::string, bool)> hook) override;
|
||||
|
||||
bool auth_async_pending(service::ConvoTag tag) const override;
|
||||
|
||||
private:
|
||||
const std::string m_AuthURL;
|
||||
const std::string m_AuthMethod;
|
||||
const Whitelist_t m_AuthWhitelist;
|
||||
const std::unordered_set<std::string> m_AuthStaticTokens;
|
||||
LMQ_ptr m_LMQ;
|
||||
Endpoint_ptr m_Endpoint;
|
||||
std::optional<oxenmq::ConnectionID> m_Conn;
|
||||
std::unordered_set<service::ConvoTag> m_PendingAuths;
|
||||
};
|
||||
} // namespace llarp::rpc
|
@ -5,8 +5,6 @@
|
||||
#include <llarp/address/ip_range.hpp>
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/router/route_poker.hpp>
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/endpoint.hpp>
|
||||
|
||||
#include <oxen/log/omq_logger.hpp>
|
||||
#include <oxenmq/address.h>
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/config/ini.hpp>
|
||||
#include <llarp/constants/version.hpp>
|
||||
#include <llarp/dns/dns.hpp>
|
||||
#include <llarp/dns/server.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/rpc/rpc_request_definitions.hpp>
|
||||
|
@ -1,73 +0,0 @@
|
||||
#include "address.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
|
||||
#include <oxenc/base32z.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
const std::set<std::string> Address::AllowedTLDs = {".loki", ".snode"};
|
||||
|
||||
bool Address::PermitTLD(const char* tld)
|
||||
{
|
||||
std::string gtld(tld);
|
||||
std::transform(gtld.begin(), gtld.end(), gtld.begin(), ::tolower);
|
||||
return AllowedTLDs.count(gtld) != 0;
|
||||
}
|
||||
|
||||
std::string Address::to_string(const char* tld) const
|
||||
{
|
||||
if (!PermitTLD(tld))
|
||||
return "";
|
||||
std::string str;
|
||||
if (subdomain.size())
|
||||
{
|
||||
str = subdomain;
|
||||
str += '.';
|
||||
}
|
||||
str += oxenc::to_base32z(begin(), end());
|
||||
str += tld;
|
||||
return str;
|
||||
}
|
||||
|
||||
bool Address::FromString(std::string_view str, const char* tld)
|
||||
{
|
||||
if (!PermitTLD(tld))
|
||||
return false;
|
||||
// Find, validate, and remove the .tld
|
||||
const auto pos = str.find_last_of('.');
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
if (str.substr(pos) != tld)
|
||||
return false;
|
||||
str = str.substr(0, pos);
|
||||
|
||||
// copy subdomains if they are there (and strip them off)
|
||||
const auto idx = str.find_last_of('.');
|
||||
if (idx != std::string::npos)
|
||||
{
|
||||
subdomain = str.substr(0, idx);
|
||||
str.remove_prefix(idx + 1);
|
||||
}
|
||||
|
||||
// Ensure we have something valid:
|
||||
// - must end in a 1-bit value: 'o' or 'y' (i.e. 10000 or 00000)
|
||||
// - must have 51 preceeding base32z chars
|
||||
// - thus we get 51*5+1 = 256 bits = 32 bytes of output
|
||||
if (str.size() != 52 || !oxenc::is_base32z(str) || !(str.back() == 'o' || str.back() == 'y'))
|
||||
return false;
|
||||
|
||||
oxenc::from_base32z(str.begin(), str.end(), begin());
|
||||
return true;
|
||||
}
|
||||
|
||||
dht::Key_t Address::ToKey() const
|
||||
{
|
||||
PubKey k;
|
||||
crypto::derive_subkey(k, PubKey(data()), 1);
|
||||
return dht::Key_t{k.as_array()};
|
||||
}
|
||||
|
||||
} // namespace llarp::service
|
@ -1,105 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/dht/key.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/util/aligned.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
struct Address : public AlignedBuffer<32>
|
||||
{
|
||||
/// if parsed using FromString this contains the subdomain
|
||||
/// this member is not used when comparing it's extra data for dns
|
||||
std::string subdomain;
|
||||
|
||||
/// list of whitelisted gtld to permit
|
||||
static const std::set<std::string> AllowedTLDs;
|
||||
|
||||
/// return true if we permit using this tld
|
||||
/// otherwise return false
|
||||
static bool PermitTLD(const char* tld);
|
||||
|
||||
std::string to_string(const char* tld = ".loki") const;
|
||||
|
||||
bool FromString(std::string_view str, const char* tld = ".loki");
|
||||
|
||||
Address() : AlignedBuffer<32>()
|
||||
{}
|
||||
|
||||
explicit Address(const std::string& str) : AlignedBuffer<32>()
|
||||
{
|
||||
if (not FromString(str))
|
||||
throw std::runtime_error("invalid address");
|
||||
}
|
||||
|
||||
explicit Address(const std::array<uint8_t, SIZE>& buf) : AlignedBuffer<32>(buf)
|
||||
{}
|
||||
|
||||
Address(const Address& other) : AlignedBuffer<32>(other.as_array()), subdomain(other.subdomain)
|
||||
{}
|
||||
|
||||
explicit Address(const AlignedBuffer<32>& other) : AlignedBuffer<32>(other)
|
||||
{}
|
||||
|
||||
bool operator<(const Address& other) const
|
||||
{
|
||||
return as_array() < other.as_array();
|
||||
}
|
||||
|
||||
bool operator==(const Address& other) const
|
||||
{
|
||||
return as_array() == other.as_array();
|
||||
}
|
||||
|
||||
bool operator!=(const Address& other) const
|
||||
{
|
||||
return as_array() != other.as_array();
|
||||
}
|
||||
|
||||
Address& operator=(const Address& other) = default;
|
||||
|
||||
dht::Key_t ToKey() const;
|
||||
|
||||
RouterID ToRouter() const
|
||||
{
|
||||
return {as_array()};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace service
|
||||
|
||||
using AddressVariant_t = std::variant<service::Address, RouterID>;
|
||||
|
||||
inline std::optional<AddressVariant_t> parse_address(std::string_view lokinet_addr)
|
||||
{
|
||||
RouterID router{};
|
||||
service::Address addr{};
|
||||
if (router.from_snode_address(lokinet_addr))
|
||||
return router;
|
||||
if (addr.FromString(lokinet_addr))
|
||||
return addr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<llarp::service::Address>
|
||||
{
|
||||
size_t operator()(const llarp::service::Address& addr) const
|
||||
{
|
||||
return std::accumulate(addr.begin(), addr.end(), 0, std::bit_xor{});
|
||||
}
|
||||
};
|
||||
} // namespace std
|
@ -1,74 +0,0 @@
|
||||
#include "async_key_exchange.hpp"
|
||||
|
||||
#include "endpoint.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
AsyncKeyExchange::AsyncKeyExchange(
|
||||
ServiceInfo r,
|
||||
const Identity& localident,
|
||||
const PQPubKey& introsetPubKey,
|
||||
const Introduction& remote,
|
||||
Endpoint* h,
|
||||
const SessionTag& t)
|
||||
: m_remote(std::move(r)),
|
||||
m_LocalIdentity(localident),
|
||||
introPubKey(introsetPubKey),
|
||||
remoteIntro(remote),
|
||||
handler(h),
|
||||
tag(t)
|
||||
{}
|
||||
|
||||
void AsyncKeyExchange::Result(std::shared_ptr<AsyncKeyExchange> self, std::shared_ptr<ProtocolFrameMessage> frame)
|
||||
{
|
||||
// put values
|
||||
// self->handler->PutSenderFor(self->msg.tag, self->m_remote, false);
|
||||
// self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey);
|
||||
// self->handler->PutIntroFor(self->msg.tag, self->remoteIntro);
|
||||
// self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply);
|
||||
self->hook(frame);
|
||||
}
|
||||
|
||||
void AsyncKeyExchange::Encrypt(std::shared_ptr<AsyncKeyExchange> self, std::shared_ptr<ProtocolFrameMessage> frame)
|
||||
{
|
||||
(void)self;
|
||||
(void)frame;
|
||||
/* TODO: client<->client session ("conversation"/"convo") key exchange
|
||||
// derive ntru session key component
|
||||
SharedSecret secret;
|
||||
crypto::pqe_encrypt(frame->cipher, secret, self->introPubKey);
|
||||
// randomize Nonce
|
||||
frame->nonce.Randomize();
|
||||
|
||||
// compute post handshake session key
|
||||
// PKE (A, B, N)
|
||||
SharedSecret sharedSecret;
|
||||
if (!self->m_LocalIdentity.KeyExchange(
|
||||
crypto::dh_client, sharedSecret, self->m_remote, frame->nonce))
|
||||
{
|
||||
log::error(logcat, "failed to derive x25519 shared key component");
|
||||
}
|
||||
|
||||
auto buf = secret.bt_encode() + sharedSecret.bt_encode();
|
||||
// H (K + PKE(A, B, N))
|
||||
crypto::shorthash(self->sharedKey, reinterpret_cast<uint8_t*>(buf.data()), buf.size());
|
||||
|
||||
// set tag
|
||||
self->msg.tag = self->tag;
|
||||
// set sender
|
||||
self->msg.sender = self->m_LocalIdentity.pub;
|
||||
// encrypt and sign
|
||||
if (frame->EncryptAndSign(self->msg, secret, self->m_LocalIdentity))
|
||||
self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); });
|
||||
else
|
||||
{
|
||||
log::error(logcat, "failed to encrypt and sign");
|
||||
}
|
||||
*/
|
||||
}
|
||||
} // namespace llarp::service
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "identity.hpp"
|
||||
#include "protocol.hpp"
|
||||
|
||||
#include <llarp/crypto/types.hpp>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
struct AsyncKeyExchange : public std::enable_shared_from_this<AsyncKeyExchange>
|
||||
{
|
||||
SharedSecret sharedKey;
|
||||
ServiceInfo m_remote;
|
||||
const Identity& m_LocalIdentity;
|
||||
ProtocolMessage msg;
|
||||
Introduction intro;
|
||||
const PQPubKey introPubKey;
|
||||
Introduction remoteIntro;
|
||||
std::function<void(std::shared_ptr<ProtocolFrameMessage>)> hook;
|
||||
Endpoint* handler;
|
||||
SessionTag tag;
|
||||
|
||||
AsyncKeyExchange(
|
||||
ServiceInfo r,
|
||||
const Identity& localident,
|
||||
const PQPubKey& introsetPubKey,
|
||||
const Introduction& remote,
|
||||
Endpoint* h,
|
||||
const SessionTag& t);
|
||||
|
||||
static void Result(std::shared_ptr<AsyncKeyExchange> user, std::shared_ptr<ProtocolFrameMessage> frame);
|
||||
|
||||
/// given protocol message make protocol frame
|
||||
static void Encrypt(std::shared_ptr<AsyncKeyExchange> user, std::shared_ptr<ProtocolFrameMessage> frame);
|
||||
};
|
||||
|
||||
} // namespace llarp::service
|
File diff suppressed because it is too large
Load Diff
@ -1,270 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "address.hpp"
|
||||
#include "identity.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <llarp/dns/server.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/net/net.hpp>
|
||||
#include <llarp/path/path_handler.hpp>
|
||||
// #include <llarp/service/address.hpp>
|
||||
// #include <llarp/service/identity.hpp>
|
||||
// #include <llarp/service/protocol.hpp>
|
||||
// #include <llarp/service/session.hpp>
|
||||
#include <llarp/util/compare_ptr.hpp>
|
||||
#include <llarp/vpn/egres_packet_router.hpp>
|
||||
|
||||
#include <oxenc/variant.h>
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
// minimum time between introset shifts
|
||||
#ifndef MIN_SHIFT_INTERVAL
|
||||
#define MIN_SHIFT_INTERVAL 5s
|
||||
#endif
|
||||
namespace llarp::quic
|
||||
{
|
||||
class TunnelManager;
|
||||
}
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
inline constexpr auto DEFAULT_PATH_ALIGN_TIMEOUT{30s};
|
||||
|
||||
/// minimum interval for publishing introsets
|
||||
inline constexpr auto IntrosetPublishInterval = path::INTRO_PATH_SPREAD / 2;
|
||||
|
||||
/// how agressively should we retry publishing introset on failure
|
||||
inline constexpr auto IntrosetPublishRetryCooldown = 1s;
|
||||
|
||||
/// how aggressively should we retry looking up introsets
|
||||
inline constexpr auto IntrosetLookupCooldown = 250ms;
|
||||
|
||||
/// number of unique snodes we want to talk to do to ons lookups
|
||||
inline constexpr size_t MIN_ONS_LOOKUP_ENDPOINTS{2};
|
||||
|
||||
inline constexpr size_t MAX_ONS_LOOKUP_ENDPOINTS{7};
|
||||
|
||||
/** Holds all local hidden service related functionality. One hidden service can be hosted per
|
||||
client or relay instance, and is managed by this object.
|
||||
*/
|
||||
struct Endpoint final : public path::PathHandler,
|
||||
/* public EndpointBase, */ public std::enable_shared_from_this<Endpoint>
|
||||
{
|
||||
Endpoint(Router& r);
|
||||
~Endpoint() override = default;
|
||||
|
||||
std::shared_ptr<path::PathHandler> get_self() override
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
std::weak_ptr<path::PathHandler> get_weak() override
|
||||
{
|
||||
return weak_from_this();
|
||||
}
|
||||
|
||||
/// return true if we are ready to recv packets from the void.
|
||||
/// really should be ReadyForInboundTraffic() but the diff is HUGE and we need to rewrite
|
||||
/// this component anyways.
|
||||
bool is_ready() const;
|
||||
|
||||
/// return true if our introset has expired intros
|
||||
bool IntrosetIsStale() const;
|
||||
|
||||
/// construct parameters for notify hooks
|
||||
// virtual std::unordered_map<std::string, std::string>
|
||||
// NotifyParams() const;
|
||||
|
||||
virtual StatusObject ExtractStatus() const;
|
||||
|
||||
virtual bool Configure(const NetworkConfig& conf, const DnsConfig& dnsConf);
|
||||
|
||||
void Tick(std::chrono::milliseconds now) override;
|
||||
|
||||
/// return true if we have a resolvable ip address
|
||||
virtual bool HasIfAddr() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::optional<SessionTag> GetBestConvoTagFor(std::variant<Address, RouterID> addr) const
|
||||
// override;
|
||||
|
||||
/// get our ifaddr if it is set
|
||||
virtual huint128_t GetIfAddr() const
|
||||
{
|
||||
return {0};
|
||||
}
|
||||
|
||||
/// get the exit policy for our exit if we have one
|
||||
/// override me
|
||||
virtual std::optional<net::TrafficPolicy> GetExitPolicy() const
|
||||
{
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
void reset_path_state() override;
|
||||
|
||||
/// loop (via router)
|
||||
/// use when sending any data on a path
|
||||
const std::shared_ptr<EventLoop>& loop();
|
||||
|
||||
virtual bool Start();
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
oxen::quic::Address local_address() const;
|
||||
|
||||
// bool should_publish_intro(std::chrono::milliseconds now) const;
|
||||
|
||||
// TODO:
|
||||
void build_more(size_t n = 0) override;
|
||||
|
||||
void srv_records_changed();
|
||||
|
||||
void path_died(std::shared_ptr<path::Path> p) override;
|
||||
|
||||
virtual vpn::EgresPacketRouter* EgresPacketRouter()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual vpn::NetworkInterface* GetVPNInterface()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool publish_introset(const EncryptedIntroSet& i);
|
||||
|
||||
bool HandleHiddenServiceFrame(std::shared_ptr<path::Path> p, const ProtocolFrameMessage& msg);
|
||||
|
||||
// virtual bool // HasServiceAddress(const AlignedBuffer< 32 >& addr) const = 0;
|
||||
|
||||
// bool HandleDataMessage(
|
||||
// std::shared_ptr<path::Path> path,
|
||||
// const PathID_t from,
|
||||
// std::shared_ptr<ProtocolMessage> msg);
|
||||
|
||||
// virtual bool // HandleWriteIPPacket(const llarp_buffer_t& pkt,
|
||||
// std::function< huint128_t(void) > getFromIP) = 0;
|
||||
|
||||
// bool ProcessDataMessage(std::shared_ptr<ProtocolMessage> msg);
|
||||
|
||||
// TODO: move these to endpoint_base
|
||||
// "find name"
|
||||
// void lookup_name(std::string name, std::function<void(std::string, bool)> func = nullptr)
|
||||
// override;
|
||||
|
||||
// "find introset?"
|
||||
// void LookupServiceAsync(
|
||||
// std::string name,
|
||||
// std::string service,
|
||||
// std::function<void(std::vector<dns::SRVData>)> resultHandler) override;
|
||||
|
||||
const Identity& GetIdentity() const
|
||||
{
|
||||
return _identity;
|
||||
}
|
||||
|
||||
bool HandleDataDrop(std::shared_ptr<path::Path> p, const HopID& dst, uint64_t s);
|
||||
|
||||
bool CheckPathIsDead(std::shared_ptr<path::Path> p, std::chrono::milliseconds latency);
|
||||
|
||||
size_t RemoveAllConvoTagsFor(service::Address remote);
|
||||
|
||||
// bool WantsOutboundSession(const Address&) const;
|
||||
|
||||
void blacklist_snode(const RouterID& snode) override;
|
||||
|
||||
virtual std::chrono::milliseconds PathAlignmentTimeout() const
|
||||
{
|
||||
return service::DEFAULT_PATH_ALIGN_TIMEOUT;
|
||||
}
|
||||
|
||||
static constexpr auto DefaultPathEnsureTimeout = 2s;
|
||||
|
||||
void AsyncProcessAuthMessage(std::shared_ptr<ProtocolMessage> msg, std::function<void(std::string, bool)> hook);
|
||||
|
||||
void SendAuthResult(
|
||||
std::shared_ptr<path::Path> path, HopID replyPath, SessionTag tag, std::string result, bool success);
|
||||
|
||||
uint64_t GenTXID();
|
||||
|
||||
const std::set<RouterID>& SnodeBlacklist() const;
|
||||
|
||||
protected:
|
||||
void regen_and_publish_introset();
|
||||
|
||||
private:
|
||||
bool DoNetworkIsolation(bool failed);
|
||||
|
||||
virtual bool SetupNetworking()
|
||||
{
|
||||
// XXX: override me
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsolationFailed()
|
||||
{
|
||||
// XXX: override me
|
||||
return false;
|
||||
}
|
||||
|
||||
/// return true if we are ready to do outbound and inbound traffic
|
||||
bool ReadyForNetwork() const;
|
||||
|
||||
protected:
|
||||
bool ReadyToDoLookup(size_t num_paths) const;
|
||||
|
||||
auto GetUniqueEndpointsForLookup() const;
|
||||
|
||||
/** TESTNET: these are member attributes/functions moved to EndpointBase. This is to
|
||||
spread commonly used members amongst all types deriving from EndpointBase, like
|
||||
{Tun,Null}Endpoint. */
|
||||
|
||||
// bool _publish_introset = true;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/** TESTNET: these are member attributes/functions moved to service::Handler. This is
|
||||
a result of a separation of concerns between managing locally operated services
|
||||
vs our sessions to services operated remotely. service::Endpoint will manage the
|
||||
former, while service::Handler will manage the latter. */
|
||||
|
||||
/// this MUST be called if you want to call EnsurePathTo on the given address
|
||||
// void MarkAddressOutbound(service::Address) override;
|
||||
|
||||
// bool // EnsurePathTo(
|
||||
// std::variant<Address, RouterID> addr,
|
||||
// std::function<void(std::optional<ConvoTag>)> hook,
|
||||
// std::chrono::milliseconds timeout) override;
|
||||
|
||||
// /// return false if we have already called this function before for this
|
||||
// /// address
|
||||
// bool // EnsurePathToService(
|
||||
// const Address remote,
|
||||
// std::function<void(Address, OutboundContext*)> h,
|
||||
// std::chrono::milliseconds timeoutMS = DefaultPathEnsureTimeout);
|
||||
// /// ensure a path to a service node by public key
|
||||
// bool // EnsurePathToSNode(
|
||||
// const RouterID remote,
|
||||
// std::function<void(const RouterID, std::shared_ptr<session::BaseSession>, ConvoTag)>
|
||||
// h);
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
Identity _identity;
|
||||
std::unique_ptr<link::TunnelManager> _tunnel_manager;
|
||||
|
||||
private:
|
||||
std::chrono::milliseconds _last_introset_regen_attempt = 0s;
|
||||
std::set<RouterID> snode_blacklist;
|
||||
|
||||
protected:
|
||||
friend struct EndpointUtil;
|
||||
};
|
||||
} // namespace llarp::service
|
@ -1,43 +0,0 @@
|
||||
#include "endpoint_state.hpp"
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
StatusObject EndpointState::ExtractStatus(StatusObject& obj) const
|
||||
{
|
||||
obj["lastPublished"] = to_json(last_publish);
|
||||
obj["lastPublishAttempt"] = to_json(last_publish_attempt);
|
||||
obj["introset"] = local_introset.ExtractStatus();
|
||||
// static auto getSecond = [](const auto& item) -> auto
|
||||
// {
|
||||
// return item.second.ExtractStatus();
|
||||
// };
|
||||
|
||||
// std::transform(
|
||||
// dead_sessions.begin(),
|
||||
// dead_sessions.end(),
|
||||
// std::back_inserter(obj["deadSessions"]),
|
||||
// getSecond);
|
||||
// std::transform(
|
||||
// remote_sessions.begin(),
|
||||
// remote_sessions.end(),
|
||||
// std::back_inserter(obj["remoteSessions"]),
|
||||
// getSecond);
|
||||
// std::transform(
|
||||
// snode_sessions.begin(),
|
||||
// snode_sessions.end(),
|
||||
// std::back_inserter(obj["snodeSessions"]),
|
||||
// [](const auto& item) { return item.second->ExtractStatus(); });
|
||||
|
||||
StatusObject sessionObj{};
|
||||
|
||||
// TODO:
|
||||
// for (const auto& item : m_Sessions)
|
||||
// {
|
||||
// std::string k = item.first.ToHex();
|
||||
// sessionObj[k] = item.second.ExtractStatus();
|
||||
// }
|
||||
|
||||
obj["converstations"] = sessionObj;
|
||||
return obj;
|
||||
}
|
||||
} // namespace llarp::service
|
@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "address.hpp"
|
||||
#include "intro_set.hpp"
|
||||
#include "lns_tracker.hpp"
|
||||
#include "tag.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/util/compare_ptr.hpp>
|
||||
#include <llarp/util/decaying_hashtable.hpp>
|
||||
#include <llarp/util/types.hpp>
|
||||
|
||||
#include <oxenc/variant.h>
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
struct EndpointState
|
||||
{
|
||||
std::set<RouterID> snode_blacklist;
|
||||
|
||||
std::string key_file;
|
||||
std::string name;
|
||||
std::string net_NS;
|
||||
bool is_exit_enabled = false;
|
||||
|
||||
// PendingTrafficMap pending_traffic;
|
||||
// ConnectionMap remote_sessions;
|
||||
// ConnectionMap dead_sessions;
|
||||
// std::set<SessionTag> inbound_convotags;
|
||||
// SNodeConnectionMap snode_sessions;
|
||||
// PendingRoutersMap pending_routers;
|
||||
|
||||
std::chrono::milliseconds last_publish = 0s;
|
||||
std::chrono::milliseconds last_publish_attempt = 0s;
|
||||
/// our introset
|
||||
IntroSet local_introset;
|
||||
/// on initialize functions
|
||||
std::list<std::function<bool(void)>> on_init_callbacks;
|
||||
|
||||
/// conversations
|
||||
std::unordered_map<SessionTag, Session> m_Sessions;
|
||||
|
||||
llarp::util::DecayingHashTable<std::string, std::variant<Address, RouterID>, std::hash<std::string>> nameCache;
|
||||
|
||||
LNSLookupTracker lnsTracker;
|
||||
|
||||
StatusObject ExtractStatus(StatusObject& obj) const;
|
||||
};
|
||||
} // namespace llarp::service
|
@ -1,313 +0,0 @@
|
||||
#include "handler.hpp"
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include <llarp/dns/dns.hpp>
|
||||
#include <llarp/messages/common.hpp>
|
||||
#include <llarp/net/net.hpp>
|
||||
#include <llarp/nodedb.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
Handler::Handler(std::string /* name */, Router& /* r */) /* : handlers::RemoteHandler{std::move(name), r} */
|
||||
{}
|
||||
|
||||
Handler::~Handler() = default;
|
||||
|
||||
// bool Handler::EnsurePathTo(
|
||||
// AddressVariant_t addr,
|
||||
// std::function<void(std::optional<service::SessionTag>)> hook,
|
||||
// std::chrono::milliseconds)
|
||||
// {
|
||||
// if (std::holds_alternative<service::Address>(addr))
|
||||
// return false;
|
||||
// if (auto* rid = std::get_if<RouterID>(&addr))
|
||||
// {
|
||||
// if (snode_keys.count(PubKey{*rid}) or _router.PathToRouterAllowed(*rid))
|
||||
// {
|
||||
// // ObtainSNodeSession(
|
||||
// // *rid, [hook, routerID = *rid](std::shared_ptr<session::BaseSession> session) {
|
||||
// // if (session and session->IsReady())
|
||||
// // {
|
||||
// // if (auto path = session->GetPathByRouter(routerID))
|
||||
// // {
|
||||
// // hook(service::ConvoTag{path->RXID().as_array()});
|
||||
// // }
|
||||
// // else
|
||||
// // hook(std::nullopt);
|
||||
// // }
|
||||
// // else
|
||||
// // hook(std::nullopt);
|
||||
// // });
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // probably a client
|
||||
// hook(GetBestConvoTagFor(addr));
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
void Handler::_configure()
|
||||
{}
|
||||
|
||||
StatusObject Handler::ExtractStatus() const
|
||||
{
|
||||
// StatusObject obj{{"permitExit", permit_exit}, {"ip", if_addr.to_string()}};
|
||||
// StatusObject exitsObj{};
|
||||
// for (const auto& item : active_exits)
|
||||
// {
|
||||
// exitsObj[item.first.to_string()] = item.second->ExtractStatus();
|
||||
// }
|
||||
// obj["exits"] = exitsObj;
|
||||
return {};
|
||||
}
|
||||
|
||||
// bool Handler::should_hook_dns_msg(const dns::Message& msg) const
|
||||
// {
|
||||
// if (msg.questions.size() == 0)
|
||||
// return false;
|
||||
// // always hook ptr for ranges we own
|
||||
// if (msg.questions[0].qtype == dns::qTypePTR)
|
||||
// {
|
||||
// if (auto ip = dns::DecodePTR(msg.questions[0].qname))
|
||||
// return ip_range.Contains(*ip);
|
||||
// return false;
|
||||
// }
|
||||
// if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeCNAME
|
||||
// || msg.questions[0].qtype == dns::qTypeAAAA)
|
||||
// {
|
||||
// if (msg.questions[0].IsName("localhost.loki"))
|
||||
// return true;
|
||||
// if (msg.questions[0].HasTLD(".snode"))
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool Handler::MaybeHookDNS(
|
||||
// std::shared_ptr<dns::PacketSource_Base> source,
|
||||
// const dns::Message& query,
|
||||
// const SockAddr& to,
|
||||
// const SockAddr& from)
|
||||
// {
|
||||
// if (not ShouldHookDNSMessage(query))
|
||||
// return false;
|
||||
|
||||
// (void)source;
|
||||
// (void)to;
|
||||
// (void)from;
|
||||
|
||||
// // auto job = std::make_shared<dns::QueryJob>(source, query, to, from);
|
||||
// // if (not HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer());
|
||||
// }))
|
||||
// // job->Cancel();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// bool Handler::handle_hooked_dns_msg(dns::Message msg, std::function<void(dns::Message)>
|
||||
// reply)
|
||||
// {
|
||||
// if (msg.questions[0].qtype == dns::qTypePTR)
|
||||
// {
|
||||
// auto ip = dns::DecodePTR(msg.questions[0].qname);
|
||||
// if (not ip)
|
||||
// return false;
|
||||
// if (ip == _if_addr)
|
||||
// {
|
||||
// RouterID us = _router.pubkey();
|
||||
// msg.AddAReply(us.to_string(), 300);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// auto itr = ip_to_key.find(*ip);
|
||||
// if (itr != ip_to_key.end() && snode_keys.find(itr->second) != snode_keys.end())
|
||||
// {
|
||||
// RouterID them{itr->second.data()};
|
||||
// msg.AddAReply(them.to_string());
|
||||
// }
|
||||
// else
|
||||
// msg.AddNXReply();
|
||||
// }
|
||||
// }
|
||||
// else if (msg.questions[0].qtype == dns::qTypeCNAME)
|
||||
// {
|
||||
// if (msg.questions[0].IsName("random.snode"))
|
||||
// {
|
||||
// if (auto random = _router.GetRandomGoodRouter())
|
||||
// msg.AddCNAMEReply(random->to_string(), 1);
|
||||
// else
|
||||
// msg.AddNXReply();
|
||||
// }
|
||||
// else if (msg.questions[0].IsName("localhost.loki"))
|
||||
// {
|
||||
// RouterID us = _router.pubkey();
|
||||
// msg.AddAReply(us.to_string(), 1);
|
||||
// }
|
||||
// else
|
||||
// msg.AddNXReply();
|
||||
// }
|
||||
// else if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA)
|
||||
// {
|
||||
// const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA;
|
||||
// const bool isV4 = msg.questions[0].qtype == dns::qTypeA;
|
||||
// if (msg.questions[0].IsName("random.snode"))
|
||||
// {
|
||||
// if (auto random = _router.GetRandomGoodRouter())
|
||||
// {
|
||||
// // TODO:
|
||||
// // msg.AddCNAMEReply(random->to_string(), 1);
|
||||
// // auto ip = ObtainServiceNodeIP(*random);
|
||||
// // msg.AddINReply(ip, false);
|
||||
// }
|
||||
// else
|
||||
// msg.AddNXReply();
|
||||
// reply(msg);
|
||||
// return true;
|
||||
// }
|
||||
// if (msg.questions[0].IsName("localhost.loki"))
|
||||
// {
|
||||
// msg.AddINReply(if_addr(), isV6);
|
||||
// reply(msg);
|
||||
// return true;
|
||||
// }
|
||||
// // forward dns for snode
|
||||
// RouterID r;
|
||||
// if (r.from_snode_address(msg.questions[0].Name()))
|
||||
// {
|
||||
// huint128_t ip;
|
||||
// PubKey pubKey(r);
|
||||
// if (isV4 && supports_ipv6())
|
||||
// {
|
||||
// msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA;
|
||||
// }
|
||||
// else if (snode_keys.find(pubKey) == snode_keys.end())
|
||||
// {
|
||||
// // we do not have it mapped, async obtain it
|
||||
// ObtainSNodeSession(
|
||||
// r,
|
||||
// [&, msg = std::make_shared<dns::Message>(msg), reply](
|
||||
// std::shared_ptr<session::BaseSession> session) {
|
||||
// if (session && session->IsReady())
|
||||
// {
|
||||
// msg->AddINReply(key_to_IP[pubKey], isV6);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// msg->AddNXReply();
|
||||
// }
|
||||
// reply(*msg);
|
||||
// });
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // we have it mapped already as a service node
|
||||
// auto itr = key_to_IP.find(pubKey);
|
||||
// if (itr != key_to_IP.end())
|
||||
// {
|
||||
// ip = itr->second;
|
||||
// msg.AddINReply(ip, isV6);
|
||||
// }
|
||||
// else // fallback case that should never happen (probably)
|
||||
// msg.AddNXReply();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// msg.AddNXReply();
|
||||
// }
|
||||
// reply(msg);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// void Handler::ObtainSNodeSession(const RouterID& rid)
|
||||
// {
|
||||
// (void)rid;
|
||||
// // if (not _router.node_db()->is_connection_allowed(rid))
|
||||
// // {
|
||||
// // obtain_cb(nullptr);
|
||||
// // return;
|
||||
// // }
|
||||
// // ObtainServiceNodeIP(rid);
|
||||
// // snode_sessions[rid]->AddReadyHook(obtain_cb);
|
||||
// }
|
||||
|
||||
bool Handler::Start()
|
||||
{
|
||||
// map our address
|
||||
// const PubKey us(_router.pubkey());
|
||||
// const huint128_t ip = if_addr();
|
||||
// key_to_IP[us] = ip;
|
||||
// ip_to_key[ip] = us;
|
||||
// ip_activity[ip] = std::numeric_limits<std::chrono::milliseconds>::max();
|
||||
// snode_keys.insert(us);
|
||||
|
||||
// TODO: move this into router
|
||||
// if (should_init_tun)
|
||||
// {
|
||||
// vpn::InterfaceInfo info;
|
||||
// info.ifname = if_name;
|
||||
// info.addrs.emplace_back(ip_range);
|
||||
|
||||
// if_net = _router.vpn_platform()->CreateInterface(std::move(info), _router);
|
||||
// if (not if_net)
|
||||
// {
|
||||
// llarp::LogError("Could not create interface");
|
||||
// return false;
|
||||
// }
|
||||
// if (not _router.loop()->add_network_interface(
|
||||
// if_net, [this](net::IPPacket pkt) { OnInetPacket(std::move(pkt)); }))
|
||||
// {
|
||||
// llarp::LogWarn("Could not create tunnel for exit endpoint");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // _router.loop()->add_ticker([this] { Flush(); });
|
||||
// #ifndef _WIN32
|
||||
// resolver =
|
||||
// std::make_shared<dns::Server>(_router.loop(), dns_conf,
|
||||
// if_nametoindex(if_name.c_str()));
|
||||
// resolver->Start();
|
||||
|
||||
// #endif
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
// bool Handler::HasLocalMappedAddrFor(const PubKey& pk) const
|
||||
// {
|
||||
// return key_to_IP.find(pk) != key_to_IP.end();
|
||||
// }
|
||||
|
||||
// huint128_t
|
||||
// Handler::ObtainServiceNodeIP(const RouterID& other) // "find router"
|
||||
// {
|
||||
// const PubKey pubKey{other};
|
||||
// const PubKey us{_router.pubkey()};
|
||||
// // just in case
|
||||
// if (pubKey == us)
|
||||
// return if_addr;
|
||||
|
||||
// huint128_t ip = GetIPForIdent(pubKey);
|
||||
// // if (snode_keys.emplace(pubKey).second)
|
||||
// // {
|
||||
// // auto session = std::make_shared<exit::SNodeSession>(
|
||||
// // other,
|
||||
// // [this, ip](const auto& buf) { return QueueSNodePacket(buf, ip); },
|
||||
// // _router,
|
||||
// // 2,
|
||||
// // 1,
|
||||
// // true,
|
||||
// // this);
|
||||
// // // this is a new service node make an outbound session to them
|
||||
// // snode_sessions[other] = session;
|
||||
// // }
|
||||
// return ip;
|
||||
// }
|
||||
|
||||
} // namespace llarp::service
|
@ -1,85 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/handlers/remote.hpp>
|
||||
#include <llarp/session/session.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct Router;
|
||||
}
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
/** Will handle all sessions to remote hidden services operated by either a
|
||||
client or a snode. This is NOT handling any thing related to clearnet
|
||||
exit nodes.
|
||||
*/
|
||||
struct Handler final : /* public handlers::RemoteHandler, */ public std::enable_shared_from_this<Handler>
|
||||
{
|
||||
Handler(std::string name, Router& r);
|
||||
~Handler();
|
||||
|
||||
// std::shared_ptr<PathHandler> get_self()
|
||||
// {
|
||||
// return shared_from_this();
|
||||
// }
|
||||
|
||||
// std::weak_ptr<PathHandler> get_weak()
|
||||
// {
|
||||
// return weak_from_this();
|
||||
// }
|
||||
|
||||
StatusObject ExtractStatus() const;
|
||||
|
||||
// bool should_hook_dns_msg(const dns::Message& msg) const;
|
||||
|
||||
// bool handle_hooked_dns_msg(dns::Message msg, std::function<void(dns::Message)>);
|
||||
|
||||
/// sets up networking and starts traffic
|
||||
bool Start();
|
||||
|
||||
// bool HasLocalMappedAddrFor(const PubKey& pk) const;
|
||||
|
||||
// huint128_t GetIPForIdent(const PubKey pk);
|
||||
|
||||
private:
|
||||
void _configure();
|
||||
// huint128_t AllocateNewAddress();
|
||||
/// obtain ip for service node session, creates a new session if one does
|
||||
/// not existing already
|
||||
// huint128_t ObtainServiceNodeIP(const RouterID& router);
|
||||
|
||||
// void MarkIPActive(huint128_t ip);
|
||||
|
||||
// void KickIdentOffExit(const PubKey& pk);
|
||||
|
||||
// bool should_init_tun;
|
||||
// std::shared_ptr<dns::Server> resolver;
|
||||
|
||||
// std::unordered_map<PubKey, huint128_t> key_to_IP;
|
||||
|
||||
// /// set of pubkeys we treat as snodes
|
||||
// std::set<PubKey> snode_keys;
|
||||
|
||||
// std::unordered_map<huint128_t, PubKey> ip_to_key;
|
||||
|
||||
// huint128_t _if_addr;
|
||||
// huint128_t highest_addr;
|
||||
|
||||
// huint128_t next_addr;
|
||||
// IPRange ip_range;
|
||||
// std::string if_name;
|
||||
|
||||
// std::unordered_map<huint128_t, std::chrono::milliseconds> ip_activity;
|
||||
|
||||
// std::shared_ptr<vpn::NetworkInterface> if_net;
|
||||
|
||||
// SockAddr resolver_addr;
|
||||
// std::vector<SockAddr> upstream_resolvers;
|
||||
|
||||
// std::shared_ptr<link::TunnelManager> tunnel_manager;
|
||||
};
|
||||
} // namespace llarp::service
|
@ -162,7 +162,7 @@ namespace llarp::service
|
||||
|
||||
auto bte = i.bt_encode();
|
||||
|
||||
const SharedSecret k{i.address_keys.address()};
|
||||
const SharedSecret k{i.address_keys.address().pubkey()};
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(bte.data()), bte.size(), k, encrypted.nonce);
|
||||
|
||||
std::memcpy(encrypted.introset_payload.data(), bte.data(), bte.size());
|
||||
|
@ -21,6 +21,7 @@ namespace llarp::service
|
||||
{
|
||||
vanity = *nonce;
|
||||
}
|
||||
|
||||
return update_address();
|
||||
}
|
||||
|
||||
@ -69,27 +70,29 @@ namespace llarp::service
|
||||
|
||||
std::string ServiceInfo::name() const
|
||||
{
|
||||
if (_cached_addr.is_zero())
|
||||
if (_cached_addr.is_empty())
|
||||
{
|
||||
Address addr;
|
||||
calculate_address(addr.as_array());
|
||||
return addr.to_string();
|
||||
PubKey pk;
|
||||
calculate_address(pk);
|
||||
return pk.to_string();
|
||||
}
|
||||
|
||||
return _cached_addr.to_string();
|
||||
}
|
||||
|
||||
bool ServiceInfo::calculate_address(std::array<uint8_t, 32>& data) const
|
||||
bool ServiceInfo::calculate_address(PubKey& data) const
|
||||
{
|
||||
data = signkey.as_array();
|
||||
data = PubKey{signkey.as_array()};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceInfo::update_address()
|
||||
{
|
||||
if (_cached_addr.is_zero())
|
||||
if (_cached_addr.is_empty())
|
||||
{
|
||||
return calculate_address(_cached_addr.as_array());
|
||||
return calculate_address(_cached_addr.pubkey());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "address.hpp"
|
||||
#include "vanity.hpp"
|
||||
|
||||
#include <llarp/address/address.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
|
||||
#include <oxenc/bt.h>
|
||||
@ -16,7 +16,7 @@ namespace llarp::service
|
||||
private:
|
||||
PubKey enckey;
|
||||
PubKey signkey;
|
||||
mutable Address _cached_addr;
|
||||
mutable NetworkAddress _cached_addr;
|
||||
|
||||
public:
|
||||
VanityNonce vanity;
|
||||
@ -31,10 +31,9 @@ namespace llarp::service
|
||||
|
||||
const PubKey& encryption_pubkey() const
|
||||
{
|
||||
if (_cached_addr.is_zero())
|
||||
{
|
||||
calculate_address(_cached_addr.as_array());
|
||||
}
|
||||
if (_cached_addr.is_empty())
|
||||
calculate_address(_cached_addr.pubkey());
|
||||
|
||||
return enckey;
|
||||
}
|
||||
|
||||
@ -63,17 +62,16 @@ namespace llarp::service
|
||||
|
||||
bool update_address();
|
||||
|
||||
const Address& address() const
|
||||
const NetworkAddress& address() const
|
||||
{
|
||||
if (_cached_addr.is_zero())
|
||||
{
|
||||
calculate_address(_cached_addr.as_array());
|
||||
}
|
||||
if (_cached_addr.is_empty())
|
||||
calculate_address(_cached_addr.pubkey());
|
||||
|
||||
return _cached_addr;
|
||||
}
|
||||
|
||||
/// calculate our address
|
||||
bool calculate_address(std::array<uint8_t, 32>& data) const;
|
||||
bool calculate_address(PubKey& data) const;
|
||||
|
||||
bool bt_decode(std::string_view buf);
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
#include "lns_tracker.hpp"
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
std::function<void(std::optional<LNSLookupTracker::Addr_t>)> LNSLookupTracker::MakeResultHandler(
|
||||
std::string name, std::size_t numPeers, std::function<void(std::optional<Addr_t>)> resultHandler)
|
||||
{
|
||||
m_PendingLookups.emplace(name, LookupInfo{numPeers, resultHandler});
|
||||
return [name, this](std::optional<Addr_t> found) {
|
||||
auto itr = m_PendingLookups.find(name);
|
||||
if (itr == m_PendingLookups.end())
|
||||
return;
|
||||
itr->second.HandleOneResult(found);
|
||||
if (itr->second.IsDone())
|
||||
m_PendingLookups.erase(itr);
|
||||
};
|
||||
}
|
||||
|
||||
bool LNSLookupTracker::LookupInfo::IsDone() const
|
||||
{
|
||||
return m_ResultsGotten == m_ResultsNeeded;
|
||||
}
|
||||
|
||||
void LNSLookupTracker::LookupInfo::HandleOneResult(std::optional<Addr_t> result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
m_CurrentValues.insert(*result);
|
||||
}
|
||||
m_ResultsGotten++;
|
||||
if (IsDone())
|
||||
{
|
||||
if (m_CurrentValues.size() == 1)
|
||||
{
|
||||
m_HandleResult(*m_CurrentValues.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HandleResult(std::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace llarp::service
|
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "address.hpp"
|
||||
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
#include <oxenc/variant.h>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
/// tracks and manages consensus of lns names we fetch from the network
|
||||
class LNSLookupTracker
|
||||
{
|
||||
public:
|
||||
using Addr_t = std::variant<Address, RouterID>;
|
||||
|
||||
private:
|
||||
struct LookupInfo
|
||||
{
|
||||
std::unordered_set<Addr_t> m_CurrentValues;
|
||||
std::function<void(std::optional<Addr_t>)> m_HandleResult;
|
||||
std::size_t m_ResultsGotten = 0;
|
||||
std::size_t m_ResultsNeeded;
|
||||
|
||||
LookupInfo(std::size_t wantResults, std::function<void(std::optional<Addr_t>)> resultHandler)
|
||||
: m_HandleResult{std::move(resultHandler)}, m_ResultsNeeded{wantResults}
|
||||
{}
|
||||
|
||||
bool IsDone() const;
|
||||
|
||||
void HandleOneResult(std::optional<Addr_t> result);
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, LookupInfo> m_PendingLookups;
|
||||
|
||||
public:
|
||||
/// make a function that will handle consensus of an lns request
|
||||
/// name is the name we are requesting
|
||||
/// numPeers is the number of peers we asked
|
||||
/// resultHandler is a function that we are wrapping that will handle the final result
|
||||
std::function<void(std::optional<Addr_t>)> MakeResultHandler(
|
||||
std::string name, std::size_t numPeers, std::function<void(std::optional<Addr_t>)> resultHandler);
|
||||
};
|
||||
} // namespace llarp::service
|
@ -1,459 +0,0 @@
|
||||
#include "protocol.hpp"
|
||||
|
||||
#include "endpoint.hpp"
|
||||
|
||||
#include <llarp/path/path.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/util/buffer.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
static auto logcat = log::Cat("Protocol");
|
||||
|
||||
ProtocolMessage::ProtocolMessage()
|
||||
{
|
||||
tag.zero();
|
||||
}
|
||||
|
||||
ProtocolMessage::ProtocolMessage(const SessionTag& t) : tag(t)
|
||||
{}
|
||||
|
||||
ProtocolMessage::~ProtocolMessage() = default;
|
||||
|
||||
void ProtocolMessage::put_buffer(std::string buf)
|
||||
{
|
||||
payload.resize(buf.size());
|
||||
memcpy(payload.data(), buf.data(), buf.size());
|
||||
}
|
||||
|
||||
void ProtocolMessage::process_async(
|
||||
std::shared_ptr<path::Path> path, HopID from, std::shared_ptr<ProtocolMessage> self)
|
||||
{
|
||||
(void)path;
|
||||
(void)from;
|
||||
(void)self;
|
||||
// if (!self->handler->HandleDataMessage(path, from, self))
|
||||
// LogWarn("failed to handle data message from ", path->name());
|
||||
}
|
||||
|
||||
bool ProtocolMessage::bt_decode(std::string_view buf)
|
||||
{
|
||||
try
|
||||
{
|
||||
oxenc::bt_dict_consumer btdc{buf};
|
||||
bt_decode(btdc);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
// DISCUSS: rethrow or print warning/return false...?
|
||||
auto err = "ProtocolMessage parsing exception: {}"_format(e.what());
|
||||
log::warning(logcat, "{}", err);
|
||||
throw std::runtime_error{err};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProtocolMessage::bt_decode(oxenc::bt_dict_consumer& btdc)
|
||||
{
|
||||
try
|
||||
{
|
||||
proto = ProtocolType{btdc.require<uint64_t>("p")};
|
||||
|
||||
if (auto maybe_payload = btdc.maybe<ustring>("d"))
|
||||
{
|
||||
payload = std::vector<uint8_t>(*maybe_payload->data(), maybe_payload->size());
|
||||
}
|
||||
|
||||
{
|
||||
auto [key, subdict] = btdc.next_dict_consumer();
|
||||
|
||||
if (key != "i")
|
||||
throw std::invalid_argument{"Unexpected key (expected:'i', actual:'{}')"_format(key)};
|
||||
|
||||
intro_reply.bt_decode(subdict);
|
||||
}
|
||||
|
||||
{
|
||||
auto [key, subdict] = btdc.next_dict_consumer();
|
||||
|
||||
if (key != "s")
|
||||
throw std::invalid_argument{"Unexpected key (expected:'s', actual:'{}')"_format(key)};
|
||||
|
||||
sender.bt_decode(subdict);
|
||||
}
|
||||
|
||||
tag.from_string(btdc.require<std::string>("t"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(logcat, "ProtocolMessage failed to populate with bt encoded contents");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ProtocolMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", static_cast<uint64_t>(proto));
|
||||
|
||||
if (not payload.empty())
|
||||
btdp.append("d", std::string_view{reinterpret_cast<const char*>(payload.data()), payload.size()});
|
||||
|
||||
{
|
||||
auto subdict = btdp.append_dict("i");
|
||||
intro_reply.bt_encode(subdict);
|
||||
}
|
||||
|
||||
{
|
||||
auto subdict = btdp.append_dict("s");
|
||||
sender.bt_encode(subdict);
|
||||
}
|
||||
|
||||
btdp.append("t", tag.to_view());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(logcat, "Error: ProtocolMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
std::vector<char> ProtocolMessage::encode_auth_info() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
// btdp.append("a", static_cast<uint64_t>(proto));
|
||||
|
||||
{
|
||||
auto subdict = btdp.append_dict("s");
|
||||
sender.bt_encode(subdict);
|
||||
}
|
||||
|
||||
btdp.append("t", tag.to_view());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(logcat, "Error: ProtocolMessage failed to bt encode auth info");
|
||||
}
|
||||
|
||||
auto view = btdp.view();
|
||||
std::vector<char> data;
|
||||
data.resize(view.size());
|
||||
|
||||
std::copy_n(view.data(), view.size(), data.data());
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ProtocolFrameMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("A", "H");
|
||||
btdp.append("C", cipher.to_view());
|
||||
btdp.append("D", std::string_view{reinterpret_cast<const char*>(enc.data()), enc.size()});
|
||||
btdp.append("F", hop_id.to_view());
|
||||
btdp.append("N", nonce.to_view());
|
||||
btdp.append("R", flag);
|
||||
btdp.append("T", convo_tag.to_view());
|
||||
btdp.append("Z", sig.to_view());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(logcat, "Error: ProtocolFrameMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::decrypt_payload_to_message(const SharedSecret& sharedkey, ProtocolMessage& msg) const
|
||||
{
|
||||
Encrypted<2048> tmp = enc;
|
||||
crypto::xchacha20(tmp.data(), tmp.size(), sharedkey, nonce);
|
||||
|
||||
auto buf = tmp.to_string();
|
||||
|
||||
return msg.bt_decode(buf);
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::sign(const Identity& localIdent)
|
||||
{
|
||||
sig.zero();
|
||||
std::array<uint8_t, MAX_PROTOCOL_MESSAGE_SIZE> tmp;
|
||||
llarp_buffer_t buf(tmp);
|
||||
// encode
|
||||
auto bte = bt_encode();
|
||||
buf.write(bte.begin(), bte.end());
|
||||
|
||||
// rewind
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// sign
|
||||
return localIdent.Sign(sig, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::encrypt_and_sign(
|
||||
const ProtocolMessage& msg, const SharedSecret& sessionKey, const Identity& localIdent)
|
||||
{
|
||||
// encode message
|
||||
auto bte1 = msg.bt_encode();
|
||||
// encrypt
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(bte1.data()), bte1.size(), sessionKey, nonce);
|
||||
// put encrypted buffer
|
||||
std::memcpy(enc.data(), bte1.data(), bte1.size());
|
||||
// zero out signature
|
||||
sig.zero();
|
||||
|
||||
auto bte2 = bt_encode();
|
||||
// sign
|
||||
if (!localIdent.Sign(sig, reinterpret_cast<uint8_t*>(bte2.data()), bte2.size()))
|
||||
{
|
||||
log::error(logcat, "ProtocolFrameMessage failed to sign with local identity key!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct AsyncFrameDecrypt
|
||||
{
|
||||
std::shared_ptr<path::Path> path;
|
||||
std::shared_ptr<ProtocolMessage> msg;
|
||||
const Identity& _local_identity;
|
||||
Endpoint* handler;
|
||||
const ProtocolFrameMessage frame;
|
||||
const Introduction src_intro;
|
||||
|
||||
AsyncFrameDecrypt(
|
||||
const Identity& localIdent,
|
||||
Endpoint* h,
|
||||
std::shared_ptr<ProtocolMessage> m,
|
||||
const ProtocolFrameMessage& f,
|
||||
const Introduction& recvIntro)
|
||||
: msg(std::move(m)), _local_identity(localIdent), handler(h), frame(f), src_intro(recvIntro)
|
||||
{}
|
||||
|
||||
static void work(std::shared_ptr<AsyncFrameDecrypt> self)
|
||||
{
|
||||
SharedSecret K;
|
||||
SharedSecret shared_key;
|
||||
// copy
|
||||
ProtocolFrameMessage frame(self->frame);
|
||||
if (!crypto::pqe_decrypt(self->frame.cipher, K, pq_keypair_to_seckey(self->_local_identity.pq)))
|
||||
{
|
||||
log::error(logcat, "pqe_decrypt failed (cipher:{})", self->frame.cipher);
|
||||
self->msg.reset();
|
||||
return;
|
||||
}
|
||||
// decrypt
|
||||
// auto buf = frame.enc.Buffer();
|
||||
uint8_t* buf = frame.enc.data();
|
||||
size_t sz = frame.enc.size();
|
||||
crypto::xchacha20(buf, sz, K, self->frame.nonce);
|
||||
|
||||
auto bte = self->msg->bt_encode();
|
||||
|
||||
if (bte.empty())
|
||||
{
|
||||
log::error(logcat, "Failed to decode inner protocol message");
|
||||
// DumpBuffer(*buf);
|
||||
self->msg.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// verify signature of outer message after we parsed the inner message
|
||||
if (!self->frame.verify(self->msg->sender))
|
||||
{
|
||||
log::error(
|
||||
logcat,
|
||||
"Intro frame has invalid signature (sig:{}, from:{})",
|
||||
self->frame.sig,
|
||||
self->msg->sender.address());
|
||||
self->msg.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// if (self->handler->HasConvoTag(self->msg->tag))
|
||||
// {
|
||||
// LogError("dropping duplicate convo tag T=", self->msg->tag);
|
||||
// // TODO: send convotag reset
|
||||
// self->msg.reset();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// PKE (A, B, N)
|
||||
SharedSecret shared_secret;
|
||||
|
||||
if (!crypto::dh_server(
|
||||
shared_secret,
|
||||
self->msg->sender.encryption_pubkey(),
|
||||
self->_local_identity.enckey,
|
||||
self->frame.nonce))
|
||||
{
|
||||
log::error(logcat, "X25519 key exchange failed!");
|
||||
self->msg.reset();
|
||||
return;
|
||||
}
|
||||
std::array<uint8_t, 64> tmp;
|
||||
// K
|
||||
std::memcpy(tmp.begin(), K.begin(), K.size());
|
||||
// S = HS( K + PKE( A, B, N))
|
||||
std::memcpy(tmp.begin() + 32, shared_secret.begin(), shared_secret.size());
|
||||
|
||||
crypto::shorthash(shared_key, tmp.data(), tmp.size());
|
||||
|
||||
std::shared_ptr<ProtocolMessage> msg = std::move(self->msg);
|
||||
std::shared_ptr<path::Path> path = std::move(self->path);
|
||||
const HopID from = self->frame.hop_id;
|
||||
msg->handler = self->handler;
|
||||
// self->handler->AsyncProcessAuthMessage(
|
||||
// msg,
|
||||
// [path, msg, from, handler = self->handler, fromIntro = self->fromIntro,
|
||||
// shared_key](
|
||||
// std::string result, bool success) {
|
||||
// if (success)
|
||||
// {
|
||||
// if (handler->WantsOutboundSession(msg->sender.Addr()))
|
||||
// {
|
||||
// handler->PutSenderFor(msg->tag, msg->sender, false);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// handler->PutSenderFor(msg->tag, msg->sender, true);
|
||||
// }
|
||||
// handler->PutReplyIntroFor(msg->tag, msg->introReply);
|
||||
// handler->PutCachedSessionKeyFor(msg->tag, shared_key);
|
||||
// handler->SendAuthResult(path, from, msg->tag, result, success);
|
||||
|
||||
// log::info(
|
||||
// logcat, "Auth accepted for tag {} from sender {}", msg->tag,
|
||||
// msg->sender.Addr());
|
||||
// ProtocolMessage::ProcessAsync(path, from, msg);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log::warning(logcat, "Auth invalid for tag {} (code: {})", msg->tag, result);
|
||||
// }
|
||||
|
||||
// handler->Pump(time_now_ms());
|
||||
// });
|
||||
}
|
||||
};
|
||||
|
||||
struct AsyncDecrypt
|
||||
{
|
||||
ServiceInfo si;
|
||||
SharedSecret shared;
|
||||
ProtocolFrameMessage frame;
|
||||
};
|
||||
|
||||
bool ProtocolFrameMessage::async_decrypt_verify(
|
||||
std::shared_ptr<path::Path> recvPath,
|
||||
const Identity& localIdent,
|
||||
Endpoint* handler,
|
||||
std::function<void(std::shared_ptr<ProtocolMessage>)> hook) const
|
||||
{
|
||||
auto msg = std::make_shared<ProtocolMessage>();
|
||||
msg->handler = handler;
|
||||
if (convo_tag.is_zero())
|
||||
{
|
||||
// we need to dh
|
||||
auto dh = std::make_shared<AsyncFrameDecrypt>(localIdent, handler, msg, *this, recvPath->intro);
|
||||
dh->path = recvPath;
|
||||
handler->router().queue_work([dh = std::move(dh)] { return AsyncFrameDecrypt::work(dh); });
|
||||
return true;
|
||||
}
|
||||
|
||||
auto v = std::make_shared<AsyncDecrypt>();
|
||||
|
||||
// if (!handler->GetCachedSessionKeyFor(convo_tag, v->shared))
|
||||
// {
|
||||
// LogError("No cached session for T=", convo_tag);
|
||||
// return false;
|
||||
// }
|
||||
// if (v->shared.IsZero())
|
||||
// {
|
||||
// LogError("bad cached session key for T=", convo_tag);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!handler->GetSenderFor(convo_tag, v->si))
|
||||
// {
|
||||
// LogError("No sender for T=", convo_tag);
|
||||
// return false;
|
||||
// }
|
||||
// if (v->si.Addr().IsZero())
|
||||
// {
|
||||
// LogError("Bad sender for T=", convo_tag);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
v->frame = *this;
|
||||
auto callback = [loop = handler->loop(), hook](std::shared_ptr<ProtocolMessage> msg) {
|
||||
if (hook)
|
||||
{
|
||||
loop->call([msg, hook]() { hook(msg); });
|
||||
}
|
||||
};
|
||||
// handler->router()->queue_work(
|
||||
// [v, msg = std::move(msg), recvPath = std::move(recvPath), callback, handler]() {
|
||||
// auto resetTag =
|
||||
// [handler, tag = v->frame.convo_tag, from = v->frame.path_id, path = recvPath]()
|
||||
// {
|
||||
// handler->ResetConvoTag(tag, path, from);
|
||||
// };
|
||||
|
||||
// if (not v->frame.Verify(v->si))
|
||||
// {
|
||||
// LogError("Signature failure from ", v->si.Addr());
|
||||
// handler->Loop()->call_soon(resetTag);
|
||||
// return;
|
||||
// }
|
||||
// if (not v->frame.DecryptPayloadInto(v->shared, *msg))
|
||||
// {
|
||||
// LogError("failed to decrypt message from ", v->si.Addr());
|
||||
// handler->Loop()->call_soon(resetTag);
|
||||
// return;
|
||||
// }
|
||||
// callback(msg);
|
||||
// RecvDataEvent ev;
|
||||
// ev.fromPath = std::move(recvPath);
|
||||
// ev.pathid = v->frame.path_id;
|
||||
// auto* handler = msg->handler;
|
||||
// ev.msg = std::move(msg);
|
||||
// handler->QueueRecvData(std::move(ev));
|
||||
// });
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::operator==(const ProtocolFrameMessage& other) const
|
||||
{
|
||||
return cipher == other.cipher && enc == other.enc && nonce == other.nonce && sig == other.sig
|
||||
&& convo_tag == other.convo_tag;
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::verify(const ServiceInfo& svc) const
|
||||
{
|
||||
ProtocolFrameMessage copy(*this);
|
||||
copy.sig.zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return svc.verify(reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
bool ProtocolFrameMessage::handle_message(Router* /*r*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp::service
|
@ -1,137 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "identity.hpp"
|
||||
#include "intro.hpp"
|
||||
|
||||
#include <llarp/crypto/encrypted.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/ev/loop.hpp>
|
||||
#include <llarp/path/path_handler.hpp>
|
||||
#include <llarp/service/tag.hpp>
|
||||
#include <llarp/util/time.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct llarp_threadpool;
|
||||
|
||||
/** TODO:
|
||||
- All of the references to service::Endpoint must be changed to EndpointBase
|
||||
- Now that there are four objects handling local/remote hidden service/exit node sessions,
|
||||
each of the four will need to handle ProtocolMessage objects and the ProtocolMessageFrames
|
||||
that contain them
|
||||
*/
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace path
|
||||
{
|
||||
/// forward declare
|
||||
struct Path;
|
||||
} // namespace path
|
||||
|
||||
namespace service
|
||||
{
|
||||
struct Endpoint;
|
||||
|
||||
inline constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE{4096};
|
||||
|
||||
/// inner message
|
||||
struct ProtocolMessage
|
||||
{
|
||||
ProtocolMessage(const SessionTag& tag);
|
||||
ProtocolMessage();
|
||||
~ProtocolMessage();
|
||||
ProtocolType proto = ProtocolType::TrafficV4;
|
||||
std::chrono::milliseconds queued = 0s;
|
||||
std::vector<uint8_t> payload; // encrypted AbstractLinkMessage
|
||||
Introduction intro_reply;
|
||||
ServiceInfo sender;
|
||||
Endpoint* handler = nullptr;
|
||||
SessionTag tag;
|
||||
std::chrono::milliseconds creation_time{time_now_ms()};
|
||||
|
||||
/// encode metainfo for lmq endpoint auth
|
||||
std::vector<char> encode_auth_info() const;
|
||||
|
||||
std::string bt_encode() const;
|
||||
|
||||
bool bt_decode(std::string_view buf);
|
||||
|
||||
void bt_decode(oxenc::bt_dict_consumer& btdc);
|
||||
|
||||
void put_buffer(std::string buf);
|
||||
|
||||
static void process_async(std::shared_ptr<path::Path> p, HopID from, std::shared_ptr<ProtocolMessage> self);
|
||||
|
||||
bool operator>(const ProtocolMessage& other) const
|
||||
{
|
||||
return creation_time > other.creation_time;
|
||||
}
|
||||
};
|
||||
|
||||
/// outer message
|
||||
struct ProtocolFrameMessage
|
||||
{
|
||||
PQCipherBlock cipher;
|
||||
Encrypted<2048> enc;
|
||||
uint64_t flag; // set to indicate in plaintext a nack, aka "dont try again"
|
||||
SymmNonce nonce;
|
||||
Signature sig;
|
||||
HopID hop_id;
|
||||
service::SessionTag convo_tag;
|
||||
|
||||
ProtocolFrameMessage(const ProtocolFrameMessage& other) = default;
|
||||
|
||||
ProtocolFrameMessage()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
~ProtocolFrameMessage() = default;
|
||||
|
||||
bool operator==(const ProtocolFrameMessage& other) const;
|
||||
|
||||
bool operator!=(const ProtocolFrameMessage& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
ProtocolFrameMessage& operator=(const ProtocolFrameMessage& other) = default;
|
||||
|
||||
bool encrypt_and_sign(
|
||||
const ProtocolMessage& msg, const SharedSecret& sharedkey, const Identity& localIdent);
|
||||
|
||||
bool sign(const Identity& localIdent);
|
||||
|
||||
bool async_decrypt_verify(
|
||||
std::shared_ptr<path::Path> fromPath,
|
||||
const Identity& localIdent,
|
||||
Endpoint* handler,
|
||||
std::function<void(std::shared_ptr<ProtocolMessage>)> hook = nullptr) const;
|
||||
|
||||
bool decrypt_payload_to_message(const SharedSecret& sharedkey, ProtocolMessage& into) const;
|
||||
|
||||
/** Note: this method needs to be re-examined where it is called in the other class
|
||||
methods, like ::Sign(), ::EncryptAndSign(), and ::Verify(). In all 3 of these cases,
|
||||
the subsequent methods that the llarp_buffer_t is passed to must be refactored to
|
||||
take either a string, a redesigned llarp_buffer, or some span backport.
|
||||
*/
|
||||
std::string bt_encode() const;
|
||||
|
||||
void clear()
|
||||
{
|
||||
cipher.zero();
|
||||
enc.Clear();
|
||||
hop_id.zero();
|
||||
convo_tag.zero();
|
||||
nonce.zero();
|
||||
sig.zero();
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
bool verify(const ServiceInfo& from) const;
|
||||
|
||||
bool handle_message(Router* r) const;
|
||||
};
|
||||
} // namespace service
|
||||
} // namespace llarp
|
@ -8,7 +8,7 @@ namespace llarp::service
|
||||
{"lastSend", to_json(lastSend)},
|
||||
{"lastRecv", to_json(lastRecv)},
|
||||
{"replyIntro", replyIntro.ExtractStatus()},
|
||||
{"remote", Addr().to_string()},
|
||||
// {"remote", Addr().to_string()},
|
||||
{"seqno", seqno},
|
||||
{"tx", messagesSend},
|
||||
{"rx", messagesRecv},
|
||||
@ -16,10 +16,10 @@ namespace llarp::service
|
||||
return obj;
|
||||
}
|
||||
|
||||
Address Session::Addr() const
|
||||
{
|
||||
return remote.address();
|
||||
}
|
||||
// Address Session::Addr() const
|
||||
// {
|
||||
// return remote.address();
|
||||
// }
|
||||
|
||||
bool Session::IsExpired(std::chrono::milliseconds now, std::chrono::milliseconds lifetime) const
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace llarp::service
|
||||
|
||||
bool IsExpired(std::chrono::milliseconds now, std::chrono::milliseconds lifetime = SessionLifetime) const;
|
||||
|
||||
Address Addr() const;
|
||||
// Address Addr() const;
|
||||
};
|
||||
|
||||
} // namespace llarp::service
|
||||
|
@ -20,7 +20,7 @@ namespace llarp::vpn
|
||||
_ports.erase(localport);
|
||||
}
|
||||
|
||||
void HandleIPPacketFrom(AddressVariant_t from, UDPPacket pkt) override
|
||||
void HandleIPPacketFrom(NetworkAddress from, IPPacket pkt) override
|
||||
{
|
||||
(void)from;
|
||||
(void)pkt;
|
||||
@ -46,7 +46,7 @@ namespace llarp::vpn
|
||||
explicit EgresGenericLayer4Handler(EgresPacketHandlerFunc baseHandler) : _handler{std::move(baseHandler)}
|
||||
{}
|
||||
|
||||
void HandleIPPacketFrom(AddressVariant_t from, UDPPacket pkt) override
|
||||
void HandleIPPacketFrom(NetworkAddress from, IPPacket pkt) override
|
||||
{
|
||||
// TOFIX: this
|
||||
(void)from;
|
||||
@ -58,7 +58,7 @@ namespace llarp::vpn
|
||||
EgresPacketRouter::EgresPacketRouter(EgresPacketHandlerFunc baseHandler) : _handler{std::move(baseHandler)}
|
||||
{}
|
||||
|
||||
void EgresPacketRouter::HandleIPPacketFrom(AddressVariant_t from, UDPPacket pkt)
|
||||
void EgresPacketRouter::HandleIPPacketFrom(NetworkAddress from, IPPacket pkt)
|
||||
{
|
||||
(void)from;
|
||||
(void)pkt;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/address/address.hpp>
|
||||
#include <llarp/address/ip_packet.hpp>
|
||||
#include <llarp/endpoint_base.hpp>
|
||||
#include <llarp/net/net_int.hpp>
|
||||
@ -9,13 +10,13 @@
|
||||
|
||||
namespace llarp::vpn
|
||||
{
|
||||
using EgresPacketHandlerFunc = std::function<void(AddressVariant_t, IPPacket)>;
|
||||
using EgresPacketHandlerFunc = std::function<void(NetworkAddress, IPPacket)>;
|
||||
|
||||
struct EgresLayer4Handler
|
||||
{
|
||||
virtual ~EgresLayer4Handler() = default;
|
||||
|
||||
virtual void HandleIPPacketFrom(AddressVariant_t from, UDPPacket pkt) = 0;
|
||||
virtual void HandleIPPacketFrom(NetworkAddress from, IPPacket pkt) = 0;
|
||||
|
||||
virtual void AddSubHandler(uint16_t, EgresPacketHandlerFunc){};
|
||||
virtual void RemoveSubHandler(uint16_t){};
|
||||
@ -31,7 +32,7 @@ namespace llarp::vpn
|
||||
explicit EgresPacketRouter(EgresPacketHandlerFunc baseHandler);
|
||||
|
||||
/// feed in an ip packet for handling
|
||||
void HandleIPPacketFrom(AddressVariant_t, UDPPacket pkt);
|
||||
void HandleIPPacketFrom(NetworkAddress, IPPacket pkt);
|
||||
|
||||
/// add a non udp packet handler using ip protocol proto
|
||||
void AddIProtoHandler(uint8_t proto, EgresPacketHandlerFunc func);
|
||||
|
Loading…
Reference in New Issue
Block a user