2018-12-12 00:58:08 +00:00
|
|
|
#include <dns/server.hpp>
|
2020-02-12 20:43:37 +00:00
|
|
|
#include <dns/dns.hpp>
|
2019-01-13 16:30:07 +00:00
|
|
|
#include <crypto/crypto.hpp>
|
2019-09-01 13:26:16 +00:00
|
|
|
#include <util/thread/logic.hpp>
|
2019-02-02 23:12:42 +00:00
|
|
|
#include <array>
|
2019-07-30 23:42:13 +00:00
|
|
|
#include <utility>
|
2019-02-02 23:12:42 +00:00
|
|
|
|
2018-12-03 22:22:59 +00:00
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace dns
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
Proxy::Proxy(
|
|
|
|
llarp_ev_loop_ptr serverLoop,
|
|
|
|
Logic_ptr serverLogic,
|
|
|
|
llarp_ev_loop_ptr clientLoop,
|
|
|
|
Logic_ptr clientLogic,
|
|
|
|
IQueryHandler* h)
|
2019-07-30 23:42:13 +00:00
|
|
|
: m_ServerLoop(std::move(serverLoop))
|
|
|
|
, m_ClientLoop(std::move(clientLoop))
|
|
|
|
, m_ServerLogic(std::move(serverLogic))
|
|
|
|
, m_ClientLogic(std::move(clientLogic))
|
2019-05-22 16:20:50 +00:00
|
|
|
, m_QueryHandler(h)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
m_Client.user = this;
|
|
|
|
m_Server.user = this;
|
|
|
|
m_Client.tick = nullptr;
|
|
|
|
m_Server.tick = nullptr;
|
2018-12-04 16:35:25 +00:00
|
|
|
m_Client.recvfrom = &HandleUDPRecv_client;
|
|
|
|
m_Server.recvfrom = &HandleUDPRecv_server;
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Proxy::Stop()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::Start(const IpAddress& addr, const std::vector<IpAddress>& resolvers)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
|
|
|
m_Resolvers.clear();
|
|
|
|
m_Resolvers = resolvers;
|
2020-05-06 20:38:44 +00:00
|
|
|
const IpAddress any("0.0.0.0", 0);
|
2019-05-22 16:20:03 +00:00
|
|
|
auto self = shared_from_this();
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ClientLogic, [=]() {
|
2020-05-06 20:38:44 +00:00
|
|
|
llarp_ev_add_udp(self->m_ClientLoop.get(), &self->m_Client, any.createSockAddr());
|
2019-05-22 16:20:03 +00:00
|
|
|
});
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ServerLogic, [=]() {
|
2020-05-06 20:38:44 +00:00
|
|
|
llarp_ev_add_udp(self->m_ServerLoop.get(), &self->m_Server, addr.createSockAddr());
|
2019-05-22 16:20:03 +00:00
|
|
|
});
|
|
|
|
return true;
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
|
2019-11-01 13:40:31 +00:00
|
|
|
static Proxy::Buffer_t
|
|
|
|
CopyBuffer(const llarp_buffer_t& buf)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
std::vector<byte_t> msgbuf(buf.sz);
|
2019-11-01 13:40:31 +00:00
|
|
|
std::copy_n(buf.base, buf.sz, msgbuf.data());
|
|
|
|
return msgbuf;
|
|
|
|
}
|
|
|
|
|
2018-12-03 22:22:59 +00:00
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::HandleUDPRecv_server(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2019-11-01 13:40:31 +00:00
|
|
|
Buffer_t msgbuf = CopyBuffer(buf.underlying);
|
2020-04-07 18:38:56 +00:00
|
|
|
auto self = static_cast<Proxy*>(u->user)->shared_from_this();
|
2019-11-01 13:40:31 +00:00
|
|
|
// yes we use the server loop here because if the server loop is not the
|
|
|
|
// client loop we'll crash again
|
2020-04-07 18:38:56 +00:00
|
|
|
LogicCall(
|
2020-05-06 20:38:44 +00:00
|
|
|
self->m_ServerLogic, [self, from, msgbuf]() { self->HandlePktServer(from, msgbuf); });
|
2018-12-04 16:35:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::HandleUDPRecv_client(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf)
|
2018-12-04 16:35:25 +00:00
|
|
|
{
|
2019-11-01 13:40:31 +00:00
|
|
|
Buffer_t msgbuf = CopyBuffer(buf.underlying);
|
2020-04-07 18:38:56 +00:00
|
|
|
auto self = static_cast<Proxy*>(u->user)->shared_from_this();
|
|
|
|
LogicCall(
|
2020-05-06 20:38:44 +00:00
|
|
|
self->m_ServerLogic, [self, from, msgbuf]() { self->HandlePktClient(from, msgbuf); });
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
|
2020-05-06 20:38:44 +00:00
|
|
|
IpAddress
|
2018-12-03 22:22:59 +00:00
|
|
|
Proxy::PickRandomResolver() const
|
|
|
|
{
|
2019-04-05 16:46:11 +00:00
|
|
|
const size_t sz = m_Resolvers.size();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (sz <= 1)
|
2018-12-03 22:22:59 +00:00
|
|
|
return m_Resolvers[0];
|
|
|
|
auto itr = m_Resolvers.begin();
|
2018-12-11 00:53:11 +00:00
|
|
|
std::advance(itr, llarp::randint() % sz);
|
2018-12-03 22:22:59 +00:00
|
|
|
return *itr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Proxy::HandleTick(llarp_udp_io*)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::SendServerMessageTo(const SockAddr& to, Message msg)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2019-05-22 16:20:03 +00:00
|
|
|
auto self = shared_from_this();
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ServerLogic, [to, msg, self]() {
|
2020-04-07 18:38:56 +00:00
|
|
|
std::array<byte_t, 1500> tmp = {{0}};
|
2019-05-22 16:20:03 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (msg.Encode(&buf))
|
2019-05-22 16:20:03 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
buf.sz = buf.cur - buf.base;
|
2019-05-22 16:20:03 +00:00
|
|
|
buf.cur = buf.base;
|
|
|
|
llarp_ev_udp_sendto(&self->m_Server, to, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
llarp::LogWarn("failed to encode dns message when sending");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::SendClientMessageTo(const SockAddr& to, Message msg)
|
2019-05-22 16:20:03 +00:00
|
|
|
{
|
|
|
|
auto self = shared_from_this();
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ClientLogic, [to, msg, self]() {
|
2020-04-07 18:38:56 +00:00
|
|
|
std::array<byte_t, 1500> tmp = {{0}};
|
2019-05-22 16:20:03 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (msg.Encode(&buf))
|
2019-05-22 16:20:03 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
buf.sz = buf.cur - buf.base;
|
2019-05-22 16:20:03 +00:00
|
|
|
buf.cur = buf.base;
|
|
|
|
llarp_ev_udp_sendto(&self->m_Client, to, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
llarp::LogWarn("failed to encode dns message when sending");
|
|
|
|
});
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::HandlePktClient(const SockAddr& from, Buffer_t buf)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-02-12 20:43:37 +00:00
|
|
|
llarp_buffer_t pkt(buf);
|
2018-12-04 16:16:43 +00:00
|
|
|
MessageHeader hdr;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!hdr.Decode(&pkt))
|
2018-12-04 16:16:43 +00:00
|
|
|
{
|
2020-02-12 20:43:37 +00:00
|
|
|
llarp::LogWarn("failed to parse dns header from ", from);
|
|
|
|
return;
|
2018-12-04 16:16:43 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
TX tx = {hdr.id, from};
|
2018-12-04 16:16:43 +00:00
|
|
|
auto itr = m_Forwarded.find(tx);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (itr == m_Forwarded.end())
|
2019-05-22 16:20:03 +00:00
|
|
|
return;
|
2020-05-06 20:38:44 +00:00
|
|
|
const auto& requester = itr->second;
|
2020-04-07 18:38:56 +00:00
|
|
|
auto self = shared_from_this();
|
2020-02-12 20:43:37 +00:00
|
|
|
Message msg(hdr);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (msg.Decode(&pkt))
|
2020-02-12 20:43:37 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
|
2020-02-12 20:43:37 +00:00
|
|
|
{
|
|
|
|
msg.hdr_id = itr->first.txid;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!m_QueryHandler->HandleHookedDNSMessage(
|
|
|
|
std::move(msg),
|
2020-05-06 20:38:44 +00:00
|
|
|
std::bind(
|
|
|
|
&Proxy::SendServerMessageTo,
|
|
|
|
self,
|
|
|
|
requester.createSockAddr(),
|
|
|
|
std::placeholders::_1)))
|
2020-02-12 20:43:37 +00:00
|
|
|
{
|
|
|
|
llarp::LogWarn("failed to handle hooked dns");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ServerLogic, [=]() {
|
2019-05-22 16:20:03 +00:00
|
|
|
// forward reply to requester via server
|
2019-11-01 13:40:31 +00:00
|
|
|
const llarp_buffer_t tmpbuf(buf);
|
2020-05-06 20:38:44 +00:00
|
|
|
llarp_ev_udp_sendto(&self->m_Server, requester.createSockAddr(), tmpbuf);
|
2019-05-22 16:20:50 +00:00
|
|
|
});
|
2019-05-22 16:20:03 +00:00
|
|
|
// remove pending
|
|
|
|
m_Forwarded.erase(itr);
|
2018-12-04 16:35:25 +00:00
|
|
|
}
|
2018-12-04 16:16:43 +00:00
|
|
|
|
2018-12-04 16:35:25 +00:00
|
|
|
void
|
2020-05-06 20:38:44 +00:00
|
|
|
Proxy::HandlePktServer(const SockAddr& from, Buffer_t buf)
|
2018-12-04 16:35:25 +00:00
|
|
|
{
|
|
|
|
MessageHeader hdr;
|
2019-11-01 13:40:31 +00:00
|
|
|
llarp_buffer_t pkt(buf);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!hdr.Decode(&pkt))
|
2018-12-04 16:35:25 +00:00
|
|
|
{
|
|
|
|
llarp::LogWarn("failed to parse dns header from ", from);
|
|
|
|
return;
|
|
|
|
}
|
2019-11-01 13:40:31 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
TX tx = {hdr.id, from};
|
2018-12-04 16:35:25 +00:00
|
|
|
auto itr = m_Forwarded.find(tx);
|
2018-12-04 16:16:43 +00:00
|
|
|
Message msg(hdr);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!msg.Decode(&pkt))
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2018-12-04 16:16:43 +00:00
|
|
|
llarp::LogWarn("failed to parse dns message from ", from);
|
2018-12-03 22:22:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-10-21 13:32:24 +00:00
|
|
|
|
|
|
|
// we don't provide a DoH resolver because it requires verified TLS
|
|
|
|
// TLS needs X509/ASN.1-DER and opting into the Root CA Cabal
|
|
|
|
// thankfully mozilla added a backdoor that allows ISPs to turn it off
|
|
|
|
// so we disable DoH for firefox using mozilla's ISP backdoor
|
|
|
|
// see: https://github.com/loki-project/loki-network/issues/832
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& q : msg.questions)
|
2019-10-21 13:32:24 +00:00
|
|
|
{
|
|
|
|
// is this firefox looking for their backdoor record?
|
2020-04-07 18:38:56 +00:00
|
|
|
if (q.IsName("use-application-dns.net"))
|
2019-10-21 13:32:24 +00:00
|
|
|
{
|
|
|
|
// yea it is, let's turn off DoH because god is dead.
|
|
|
|
msg.AddNXReply();
|
|
|
|
// press F to pay respects
|
|
|
|
SendServerMessageTo(from, std::move(msg));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-22 16:20:03 +00:00
|
|
|
auto self = shared_from_this();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!m_QueryHandler->HandleHookedDNSMessage(
|
|
|
|
std::move(msg),
|
|
|
|
std::bind(&Proxy::SendServerMessageTo, self, from, std::placeholders::_1)))
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
|
|
|
llarp::LogWarn("failed to handle hooked dns");
|
|
|
|
}
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
else if (m_Resolvers.size() == 0)
|
2019-04-05 16:46:11 +00:00
|
|
|
{
|
|
|
|
// no upstream resolvers
|
|
|
|
// let's serv fail it
|
|
|
|
msg.AddServFail();
|
2019-05-22 16:20:50 +00:00
|
|
|
|
2019-05-22 16:20:03 +00:00
|
|
|
SendServerMessageTo(from, std::move(msg));
|
2019-04-05 16:46:11 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
else if (itr == m_Forwarded.end())
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
|
|
|
// new forwarded query
|
2020-04-07 18:38:56 +00:00
|
|
|
tx.from = PickRandomResolver();
|
2018-12-03 22:22:59 +00:00
|
|
|
m_Forwarded[tx] = from;
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ClientLogic, [=] {
|
2019-05-22 16:20:03 +00:00
|
|
|
// do query
|
2019-11-01 13:40:31 +00:00
|
|
|
const llarp_buffer_t tmpbuf(buf);
|
2020-05-06 20:38:44 +00:00
|
|
|
llarp_ev_udp_sendto(&self->m_Client, tx.from.createSockAddr(), tmpbuf);
|
2019-05-22 16:20:03 +00:00
|
|
|
});
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-01 13:40:31 +00:00
|
|
|
// send the query again because it's probably FEC from the requester
|
|
|
|
const auto resolver = itr->first.from;
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(m_ClientLogic, [=] {
|
2019-11-01 13:40:31 +00:00
|
|
|
// send it
|
|
|
|
const llarp_buffer_t tmpbuf(buf);
|
2020-05-06 20:38:44 +00:00
|
|
|
llarp_ev_udp_sendto(&self->m_Client, resolver.createSockAddr(), tmpbuf);
|
2019-11-01 13:40:31 +00:00
|
|
|
});
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace dns
|
|
|
|
} // namespace llarp
|