lokinet/llarp/handlers/tun.hpp
Jason Rhinelander 9dd604820f
Unleak exit mode DNS via unbound DNS trampoline on (macOS)
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).
2021-09-02 14:17:10 -04:00

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