mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-17 15:25:35 +00:00
9dd604820f
When we enable/disable exit mode on this restarts the unbound DNS responder with the DNS trampoline (or restores upstream, when disabling) to properly route DNS requests through the tunnel (because libunbound's direct requests don't get tunneled because unbound is inside the network extension).
307 lines
8.0 KiB
C++
307 lines
8.0 KiB
C++
#pragma once
|
|
|
|
#include <llarp/dns/server.hpp>
|
|
#include <llarp/ev/ev.hpp>
|
|
#include <llarp/ev/vpn.hpp>
|
|
#include <llarp/net/ip.hpp>
|
|
#include <llarp/net/ip_packet.hpp>
|
|
#include <llarp/net/net.hpp>
|
|
#include <llarp/service/endpoint.hpp>
|
|
#include <llarp/util/codel.hpp>
|
|
#include <llarp/util/thread/threading.hpp>
|
|
#include <llarp/vpn/packet_router.hpp>
|
|
|
|
#include <future>
|
|
#include <queue>
|
|
#include <type_traits>
|
|
#include <variant>
|
|
#include "service/protocol_type.hpp"
|
|
|
|
namespace llarp
|
|
{
|
|
namespace handlers
|
|
{
|
|
struct TunEndpoint : public service::Endpoint,
|
|
public dns::IQueryHandler,
|
|
public std::enable_shared_from_this<TunEndpoint>
|
|
{
|
|
TunEndpoint(AbstractRouter* r, llarp::service::Context* parent);
|
|
~TunEndpoint() override;
|
|
|
|
path::PathSet_ptr
|
|
GetSelf() override
|
|
{
|
|
return shared_from_this();
|
|
}
|
|
|
|
std::weak_ptr<path::PathSet>
|
|
GetWeak() override
|
|
{
|
|
return weak_from_this();
|
|
}
|
|
|
|
void
|
|
Thaw() override;
|
|
|
|
// Reconfigures DNS servers and restarts libunbound with the new servers. Returns the old set
|
|
// of configured dns servers.
|
|
std::vector<SockAddr>
|
|
ReconfigureDNS(std::vector<SockAddr> servers);
|
|
|
|
bool
|
|
Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override;
|
|
|
|
void
|
|
SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{};
|
|
|
|
std::string
|
|
GetIfName() const override;
|
|
|
|
void
|
|
Tick(llarp_time_t now) override;
|
|
|
|
util::StatusObject
|
|
ExtractStatus() const override;
|
|
|
|
std::unordered_map<std::string, std::string>
|
|
NotifyParams() const override;
|
|
|
|
bool
|
|
SupportsV6() const override;
|
|
|
|
bool
|
|
ShouldHookDNSMessage(const dns::Message& msg) const override;
|
|
|
|
bool
|
|
HandleHookedDNSMessage(
|
|
dns::Message query, std::function<void(dns::Message)> sendreply) override;
|
|
|
|
void
|
|
TickTun(llarp_time_t now);
|
|
|
|
bool
|
|
MapAddress(const service::Address& remote, huint128_t ip, bool SNode);
|
|
|
|
bool
|
|
Start() override;
|
|
|
|
bool
|
|
Stop() override;
|
|
|
|
bool
|
|
IsSNode() const;
|
|
|
|
/// set up tun interface, blocking
|
|
bool
|
|
SetupTun();
|
|
|
|
/// overrides Endpoint
|
|
bool
|
|
SetupNetworking() override;
|
|
|
|
/// overrides Endpoint
|
|
bool
|
|
HandleInboundPacket(
|
|
const service::ConvoTag tag,
|
|
const llarp_buffer_t& pkt,
|
|
service::ProtocolType t,
|
|
uint64_t seqno) override;
|
|
|
|
/// handle inbound traffic
|
|
bool
|
|
HandleWriteIPPacket(
|
|
const llarp_buffer_t& buf, huint128_t src, huint128_t dst, uint64_t seqno);
|
|
|
|
/// queue outbound packet to the world
|
|
bool
|
|
QueueOutboundTraffic(llarp::net::IPPacket&& pkt);
|
|
|
|
/// we got a packet from the user
|
|
void
|
|
HandleGotUserPacket(llarp::net::IPPacket pkt);
|
|
|
|
/// get the local interface's address
|
|
huint128_t
|
|
GetIfAddr() const override;
|
|
|
|
/// we have an interface addr
|
|
bool
|
|
HasIfAddr() const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
HasLocalIP(const huint128_t& ip) const;
|
|
|
|
std::optional<net::TrafficPolicy>
|
|
GetExitPolicy() const override
|
|
{
|
|
return m_TrafficPolicy;
|
|
}
|
|
|
|
std::set<IPRange>
|
|
GetOwnedRanges() const override
|
|
{
|
|
return m_OwnedRanges;
|
|
}
|
|
|
|
llarp_time_t
|
|
PathAlignmentTimeout() const override
|
|
{
|
|
return m_PathAlignmentTimeout;
|
|
}
|
|
|
|
/// ip packet against any exit policies we have
|
|
/// returns false if this traffic is disallowed by any of those policies
|
|
/// returns true otherwise
|
|
bool
|
|
ShouldAllowTraffic(const net::IPPacket& pkt) const;
|
|
|
|
/// get a key for ip address
|
|
std::optional<std::variant<service::Address, RouterID>>
|
|
ObtainAddrForIP(huint128_t ip) const override;
|
|
|
|
bool
|
|
HasAddress(const AlignedBuffer<32>& addr) const
|
|
{
|
|
return m_AddrToIP.find(addr) != m_AddrToIP.end();
|
|
}
|
|
|
|
/// get ip address for key unconditionally
|
|
huint128_t
|
|
ObtainIPForAddr(std::variant<service::Address, RouterID> addr) override;
|
|
|
|
/// flush network traffic
|
|
void
|
|
Flush();
|
|
|
|
void
|
|
ResetInternalState() override;
|
|
|
|
protected:
|
|
using PacketQueue_t = llarp::util::CoDelQueue<
|
|
net::IPPacket,
|
|
net::IPPacket::GetTime,
|
|
net::IPPacket::PutTime,
|
|
net::IPPacket::CompareOrder,
|
|
net::IPPacket::GetNow>;
|
|
|
|
/// queue for sending packets over the network from us
|
|
PacketQueue_t m_UserToNetworkPktQueue;
|
|
|
|
struct WritePacket
|
|
{
|
|
uint64_t seqno;
|
|
net::IPPacket pkt;
|
|
|
|
bool
|
|
operator<(const WritePacket& other) const
|
|
{
|
|
return other.seqno < seqno;
|
|
}
|
|
};
|
|
|
|
/// queue for sending packets to user from network
|
|
std::priority_queue<WritePacket> m_NetworkToUserPktQueue;
|
|
/// return true if we have a remote loki address for this ip address
|
|
bool
|
|
HasRemoteForIP(huint128_t ipv4) const;
|
|
|
|
/// mark this address as active
|
|
void
|
|
MarkIPActive(huint128_t ip);
|
|
|
|
/// mark this address as active forever
|
|
void
|
|
MarkIPActiveForever(huint128_t ip);
|
|
|
|
/// flush ip packets
|
|
virtual void
|
|
FlushSend();
|
|
|
|
/// flush writing ip packets to interface
|
|
void
|
|
FlushWrite();
|
|
|
|
/// maps ip to key (host byte order)
|
|
std::unordered_map<huint128_t, AlignedBuffer<32>> m_IPToAddr;
|
|
/// maps key to ip (host byte order)
|
|
std::unordered_map<AlignedBuffer<32>, huint128_t> m_AddrToIP;
|
|
|
|
/// maps key to true if key is a service node, maps key to false if key is
|
|
/// a hidden service
|
|
std::unordered_map<AlignedBuffer<32>, bool> m_SNodes;
|
|
|
|
private:
|
|
template <typename Addr_t, typename Endpoint_t>
|
|
void
|
|
SendDNSReply(
|
|
Addr_t addr,
|
|
Endpoint_t ctx,
|
|
std::shared_ptr<dns::Message> query,
|
|
std::function<void(dns::Message)> reply,
|
|
bool sendIPv6)
|
|
{
|
|
if (ctx)
|
|
{
|
|
huint128_t ip = ObtainIPForAddr(addr);
|
|
query->answers.clear();
|
|
query->AddINReply(ip, sendIPv6);
|
|
}
|
|
else
|
|
query->AddNXReply();
|
|
reply(*query);
|
|
}
|
|
/// our dns resolver
|
|
std::shared_ptr<dns::PacketHandler> m_Resolver;
|
|
|
|
/// maps ip address to timestamp last active
|
|
std::unordered_map<huint128_t, llarp_time_t> m_IPActivity;
|
|
/// our ip address (host byte order)
|
|
huint128_t m_OurIP;
|
|
/// our network interface's ipv6 address
|
|
huint128_t m_OurIPv6;
|
|
|
|
/// next ip address to allocate (host byte order)
|
|
huint128_t m_NextIP;
|
|
/// highest ip address to allocate (host byte order)
|
|
huint128_t m_MaxIP;
|
|
/// our ip range we are using
|
|
llarp::IPRange m_OurRange;
|
|
/// upstream dns resolver list
|
|
std::vector<SockAddr> m_UpstreamResolvers;
|
|
/// dns host files list
|
|
std::vector<fs::path> m_hostfiles;
|
|
/// local dns
|
|
IpAddress m_LocalResolverAddr;
|
|
/// list of strict connect addresses for hooks
|
|
std::vector<IpAddress> m_StrictConnectAddrs;
|
|
/// use v6?
|
|
bool m_UseV6;
|
|
std::string m_IfName;
|
|
|
|
std::optional<huint128_t> m_BaseV6Address;
|
|
|
|
std::shared_ptr<vpn::NetworkInterface> m_NetIf;
|
|
|
|
std::unique_ptr<vpn::PacketRouter> m_PacketRouter;
|
|
|
|
std::optional<net::TrafficPolicy> m_TrafficPolicy;
|
|
/// ranges we advetise as reachable
|
|
std::set<IPRange> m_OwnedRanges;
|
|
/// how long to wait for path alignment
|
|
llarp_time_t m_PathAlignmentTimeout;
|
|
/// idempotent wakeup for writing packets to user
|
|
std::shared_ptr<EventLoopWakeup> m_PacketSendWaker;
|
|
|
|
/// idempotent wakeup for writing messages to network
|
|
std::shared_ptr<EventLoopWakeup> m_MessageSendWaker;
|
|
|
|
/// a file to load / store the ephemeral address map to
|
|
std::optional<fs::path> m_PersistAddrMapFile;
|
|
};
|
|
|
|
} // namespace handlers
|
|
} // namespace llarp
|