lokinet/llarp/handlers/tun.hpp
Thomas Winget 4c630e0437 Large collection of changes to make android work
- Previous android java and jni code updated to work, but with much love
  still needed to make it work nicely, e.g. handling when the VPN is
  turned off.

- DNS handling refactored to allow android to intercept and handle DNS
  requests as we can't set the system DNS to use a high port
  (and apparently Chrome ignores system DNS settings anyway)

- add packet router structure to allow separate handling of specific
  intercepted traffic, e.g. UDP traffic to port 53 gets handled by our
  DNS handler rather than being naively forwarded as exit traffic.

- For now, android lokinet is exit-only and hard-coded to use exit.loki
  as its exit.  The exit will be configurable before release, but
  allowing to not use exit-only mode is more of a challenge.

- some old gitignore remnants which were matching to things we don't
  want them to (and are no longer relevant) removed

- some minor changes to CI configuration
2021-03-02 13:18:22 -05:00

270 lines
6.7 KiB
C++

#ifndef LLARP_HANDLERS_TUN_HPP
#define LLARP_HANDLERS_TUN_HPP
#include <dns/server.hpp>
#include <ev/ev.hpp>
#include <ev/vpn.hpp>
#include <net/ip.hpp>
#include <net/ip_packet.hpp>
#include <net/net.hpp>
#include <service/endpoint.hpp>
#include <util/codel.hpp>
#include <util/thread/threading.hpp>
#include <vpn/packet_router.hpp>
#include <future>
#include <queue>
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();
}
void
Thaw() override;
bool
Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override;
void
SendPacketToRemote(const llarp_buffer_t&) 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;
/// get a key for ip address
template <typename Addr_t>
Addr_t
ObtainAddrForIP(huint128_t ip, bool isSNode)
{
Addr_t addr;
auto itr = m_IPToAddr.find(ip);
if (itr != m_IPToAddr.end() and m_SNodes[itr->second] == isSNode)
{
addr = Addr_t(itr->second);
}
// found
return addr;
}
template <typename Addr_t>
bool
FindAddrForIP(Addr_t& addr, huint128_t ip);
bool
HasAddress(const AlignedBuffer<32>& addr) const
{
return m_AddrToIP.find(addr) != m_AddrToIP.end();
}
/// get ip address for key unconditionally
huint128_t
ObtainIPForAddr(const AlignedBuffer<32>& addr, bool serviceNode) override;
/// flush network traffic
void
Flush();
void
ResetInternalState() override;
protected:
bool
ShouldFlushNow(llarp_time_t now) const;
llarp_time_t m_LastFlushAt = 0s;
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();
/// 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, AlignedBuffer<32>::Hash> 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, AlignedBuffer<32>::Hash> 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 snode,
bool sendIPv6)
{
if (ctx)
{
huint128_t ip = ObtainIPForAddr(addr, snode);
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<IpAddress> m_UpstreamResolvers;
/// 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::shared_ptr<vpn::NetworkInterface> m_NetIf;
std::unique_ptr<vpn::PacketRouter> m_PacketRouter;
};
} // namespace handlers
} // namespace llarp
#endif