Merge pull request #34 from neuroscr/master

Reverse DNS support
This commit is contained in:
Jeff 2018-10-19 11:04:34 -04:00 committed by GitHub
commit f458727ff3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 198 additions and 19 deletions

View File

@ -17,7 +17,9 @@ struct dotLokiLookup
{ {
/// for timers (MAYBEFIXME? maybe we decouple this, yes pls have a generic /// for timers (MAYBEFIXME? maybe we decouple this, yes pls have a generic
/// passed in) /// passed in)
// we can use DNSc for access to the logic
struct llarp_logic *logic; struct llarp_logic *logic;
/// which ip tracker to use /// which ip tracker to use
struct dns_iptracker *ip_tracker; struct dns_iptracker *ip_tracker;

View File

@ -80,6 +80,10 @@ namespace llarp
static void static void
handleTickTun(void* u); handleTickTun(void* u);
/// get a service address for ip address
service::Address
ObtainAddrForIP(huint32_t ip);
protected: protected:
typedef llarp::util::CoDelQueue< typedef llarp::util::CoDelQueue<
net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime, net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime,
@ -92,6 +96,7 @@ namespace llarp
/// return true if we have a remote loki address for this ip address /// return true if we have a remote loki address for this ip address
bool bool
HasRemoteForIP(huint32_t ipv4) const; HasRemoteForIP(huint32_t ipv4) const;
/// get ip address for service address unconditionally /// get ip address for service address unconditionally
huint32_t huint32_t
ObtainIPForAddr(const service::Address& addr); ObtainIPForAddr(const service::Address& addr);

View File

@ -76,7 +76,7 @@ namespace llarp
constexpr bool operator <(huint32_t x) const { return h < x.h; } constexpr bool operator <(huint32_t x) const { return h < x.h; }
constexpr bool operator ==(huint32_t x) const { return h == x.h; } constexpr bool operator ==(huint32_t x) const { return h == x.h; }
struct Hash struct Hash
{ {
inline size_t inline size_t
@ -272,7 +272,7 @@ namespace llarp
{ {
// network order // network order
sockaddr_in6 _addr; sockaddr_in6 _addr;
sockaddr_in _addr4; // why do we even have this? sockaddr_in _addr4; // why do we even have this? favor cpu over memory
~Addr(){}; ~Addr(){};
Addr(){}; Addr(){};

View File

@ -43,7 +43,8 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
if(!dll) if(!dll)
{ {
llarp::LogError("DNSd dotLokiLookup is not configured"); llarp::LogError("DNSd dotLokiLookup is not configured");
// FIXME: send 404 write404_dnss_response(qr->from, qr->request);
delete qr;
return; return;
} }
@ -56,7 +57,7 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
{ {
llarp::LogWarn("Could not base32 decode address: ", llarp::LogWarn("Could not base32 decode address: ",
qr->request->question.name); qr->request->question.name);
// FIXME: send 404 write404_dnss_response(qr->from, qr->request);
delete qr; delete qr;
return; return;
} }
@ -64,7 +65,9 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
auto itr = loki_tld_lookup_cache.find(addr.ToString()); auto itr = loki_tld_lookup_cache.find(addr.ToString());
if(itr != loki_tld_lookup_cache.end()) if(itr != loki_tld_lookup_cache.end())
{ {
llarp::LogDebug("Found in .loki lookup cache");
writesend_dnss_response(itr->second->returnThis, qr->from, qr->request); writesend_dnss_response(itr->second->returnThis, qr->from, qr->request);
delete qr;
return; return;
} }
@ -93,13 +96,16 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
if(!routerHiddenServiceContext) if(!routerHiddenServiceContext)
{ {
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user); llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
write404_dnss_response(qr->from, qr->request);
delete qr;
return; return;
} }
bool mapResult = routerHiddenServiceContext->MapAddressAll( bool mapResult = routerHiddenServiceContext->MapAddressAll(
addr, free_private->hostResult); addr, free_private->hostResult);
if(!mapResult) if(!mapResult)
{ {
// FIXME: send 404 llarp::LogWarn("dotLokiLookup failed to map address");
write404_dnss_response(qr->from, qr->request);
delete qr; delete qr;
return; return;
} }
@ -129,22 +135,158 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
delete qr; delete qr;
} }
std::vector< std::string >
split(std::string str)
{
size_t pos = 0;
std::string token;
std::string s(str);
std::vector< std::string > tokens;
while((pos = s.find(".")) != std::string::npos)
{
token = s.substr(0, pos);
// llarp::LogInfo("token [", token, "]");
tokens.push_back(token);
s.erase(0, pos + 1);
}
token = s.substr(0, pos);
tokens.push_back(token);
// llarp::LogInfo("token [", token, "]");
return tokens;
}
struct reverse_handler_iter_context
{
std::string lName;
const struct sockaddr *from;
const struct dnsd_question_request *request;
};
bool
ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
{
reverse_handler_iter_context *context =
(reverse_handler_iter_context *)endpointCfg->user;
// llarp::LogInfo("context ", context->request->question.name);
// llarp::LogInfo("Checking ", lName);
llarp::handlers::TunEndpoint *tunEndpoint =
(llarp::handlers::TunEndpoint *)endpointCfg->endpoint;
if(!tunEndpoint)
{
llarp::LogError("No tunnel endpoint found");
return true; // still continue
}
// llarp::LogInfo("for ", tunEndpoint->tunif.ifaddr);
std::string checkStr(tunEndpoint->tunif.ifaddr);
std::vector< std::string > tokensSearch = split(context->lName);
std::vector< std::string > tokensCheck = split(checkStr);
// well the tunif is just one ip on a network range...
// support "b._dns-sd._udp.0.0.200.10.in-addr.arpa"
size_t searchTokens = tokensSearch.size();
std::string searchIp = tokensSearch[searchTokens - 3] + "."
+ tokensSearch[searchTokens - 4] + "." + tokensSearch[searchTokens - 5]
+ "." + tokensSearch[searchTokens - 6];
std::string checkIp = tokensCheck[0] + "." + tokensCheck[1] + "."
+ tokensCheck[2] + "." + tokensCheck[3];
llarp::LogDebug(searchIp, " vs ", checkIp);
llarp::IPRange range = llarp::iprange_ipv4(
stoi(tokensCheck[0]), stoi(tokensCheck[1]), stoi(tokensCheck[2]),
stoi(tokensCheck[3]), tunEndpoint->tunif.netmask); // create range
// hack atm to work around limitations in ipaddr_ipv4_bits and llarp::IPRange
llarp::huint32_t searchIPv4_fixed = llarp::ipaddr_ipv4_bits(
stoi(tokensSearch[searchTokens - 6]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens
- 3])); // create ip (llarp::Addr is untrustworthy atm)
llarp::huint32_t searchIPv4_search = llarp::ipaddr_ipv4_bits(
stoi(tokensSearch[searchTokens - 3]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens
- 6])); // create ip (llarp::Addr is untrustworthy atm)
// bool inRange = range.Contains(searchAddr.xtohl());
bool inRange = range.Contains(searchIPv4_search);
llarp::Addr searchAddr(searchIp);
llarp::Addr checkAddr(checkIp);
llarp::LogDebug(searchAddr, " vs ", range.ToString(), " = ",
inRange ? "inRange" : "not match");
if(inRange)
{
llarp::service::Address addr =
tunEndpoint->ObtainAddrForIP(searchIPv4_fixed);
if(addr.ToString()
== "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.loki")
{
write404_dnss_response(context->from,
(dnsd_question_request *)context->request);
}
else
{
writesend_dnss_revresponse(addr.ToString(), context->from,
(dnsd_question_request *)context->request);
}
return false;
}
return true; // we don't do anything with the result yet
}
dnsd_query_hook_response * dnsd_query_hook_response *
llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
struct dnsd_question_request *const request) struct dnsd_question_request *const request)
{ {
dnsd_query_hook_response *response = new dnsd_query_hook_response; dnsd_query_hook_response *response = new dnsd_query_hook_response;
// dotLokiLookup *dll = (dotLokiLookup response->dontLookUp = false;
// *)request->context->user; response->dontSendResponse = false;
response->dontLookUp = false; response->returnThis = nullptr;
response->dontSendResponse = false;
response->returnThis = nullptr;
llarp::LogDebug("Hooked ", name); llarp::LogDebug("Hooked ", name);
std::string lName = name; std::string lName = name;
std::transform(lName.begin(), lName.end(), lName.begin(), ::tolower); std::transform(lName.begin(), lName.end(), lName.begin(), ::tolower);
// llarp::LogDebug("Transformed ", lName);
// FIXME: probably should just read the last 5 bytes // 253.0.200.10.in-addr.arpa
if(lName.find(".loki") != std::string::npos) if(lName.find(".in-addr.arpa") != std::string::npos)
{
// llarp::LogDebug("Checking ", lName);
dotLokiLookup *dll = (dotLokiLookup *)request->context->user;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
return response;
}
// llarp::LogDebug("Starting rev iter for ", lName);
// which range?
// for each tun interface
struct reverse_handler_iter_context context;
context.lName = lName;
context.from = from;
context.request = request;
struct llarp::service::Context::endpoint_iter i;
i.user = &context;
i.index = 0;
i.visit = &ReverseHandlerIter;
bool res = routerHiddenServiceContext->iterate(i);
if(!res)
{
llarp::LogInfo("Reverse is ours");
response->dontSendResponse = true; // should have already sent it
}
else
{
llarp::LogInfo("Reverse is not ours");
}
}
else if((lName.length() > 5 && lName.substr(lName.length() - 5, 5) == ".loki")
|| (lName.length() > 6
&& lName.substr(lName.length() - 6, 6) == ".loki."))
{ {
llarp::LogInfo("Detect Loki Lookup for ", lName); llarp::LogInfo("Detect Loki Lookup for ", lName);
auto cache_check = loki_tld_lookup_cache.find(lName); auto cache_check = loki_tld_lookup_cache.find(lName);
@ -179,7 +321,7 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
llarp_logic_call_later(request->context->client.logic, llarp_logic_call_later(request->context->client.logic,
{2000, qr, &llarp_dotlokilookup_checkQuery}); {2000, qr, &llarp_dotlokilookup_checkQuery});
response->dontSendResponse = true; response->dontSendResponse = true; // will send it shortly
} }
return response; return response;
} }

View File

@ -134,6 +134,7 @@ namespace llarp
} }
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", llarp::LogInfo(Name() + " map ", addr.ToString(), " to ",
inet_ntoa({nip.n})); inet_ntoa({nip.n}));
m_IPToAddr.insert(std::make_pair(ip, addr)); m_IPToAddr.insert(std::make_pair(ip, addr));
m_AddrToIP.insert(std::make_pair(addr, ip)); m_AddrToIP.insert(std::make_pair(addr, ip));
MarkIPActiveForever(ip); MarkIPActiveForever(ip);
@ -351,6 +352,22 @@ namespace llarp
return true; return true;
} }
service::Address
TunEndpoint::ObtainAddrForIP(huint32_t ip)
{
auto itr = m_IPToAddr.find(ip);
if(itr == m_IPToAddr.end())
{
// not found
// llarp::Addr test(ip); // "/", test,
service::Address addr;
llarp::LogWarn(" not found in tun map. Sending ", addr.ToString());
return addr;
}
// found
return itr->second;
}
huint32_t huint32_t
TunEndpoint::ObtainIPForAddr(const service::Address &addr) TunEndpoint::ObtainIPForAddr(const service::Address &addr)
{ {

View File

@ -64,8 +64,8 @@ namespace llarp
while(itr != m_Endpoints.end()) while(itr != m_Endpoints.end())
{ {
i.endpoint = itr->second.get(); i.endpoint = itr->second.get();
i.visit(&i); if(!i.visit(&i))
return false;
// advance // advance
i.index++; i.index++;
itr++; itr++;
@ -136,7 +136,7 @@ namespace llarp
} }
bool bool
MappAddressAllIter(struct Context::endpoint_iter *endpointCfg) MapAddressAllIter(struct Context::endpoint_iter *endpointCfg)
{ {
Context::mapAddressAll_context *context = Context::mapAddressAll_context *context =
(Context::mapAddressAll_context *)endpointCfg->user; (Context::mapAddressAll_context *)endpointCfg->user;
@ -145,7 +145,7 @@ namespace llarp
if(!tunEndpoint) if(!tunEndpoint)
{ {
llarp::LogError("No tunnel endpoint found"); llarp::LogError("No tunnel endpoint found");
return false; return true; // still continue
} }
return tunEndpoint->MapAddress(context->serviceAddr, return tunEndpoint->MapAddress(context->serviceAddr,
context->localPrivateIpAddr.xtohl()); context->localPrivateIpAddr.xtohl());
@ -162,7 +162,7 @@ namespace llarp
struct Context::endpoint_iter i; struct Context::endpoint_iter i;
i.user = &context; i.user = &context;
i.index = 0; i.index = 0;
i.visit = &MappAddressAllIter; i.visit = &MapAddressAllIter;
return this->iterate(i); return this->iterate(i);
} }

View File

@ -5,12 +5,25 @@ struct NetTest : public ::testing::Test
{ {
}; };
TEST_F(NetTest, TestRangeContains) TEST_F(NetTest, TestRangeContains8)
{ {
ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 0, 8) ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 0, 8)
.Contains(llarp::ipaddr_ipv4_bits(10, 40, 11, 6))); .Contains(llarp::ipaddr_ipv4_bits(10, 40, 11, 6)));
} }
TEST_F(NetTest, TestRangeContains24)
{
ASSERT_TRUE(llarp::iprange_ipv4(10, 200, 0, 1, 24)
.Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
}
TEST_F(NetTest, TestRangeContainsFail)
{
ASSERT_TRUE(!llarp::iprange_ipv4(192, 168, 0, 1, 24)
.Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
}
TEST_F(NetTest, TestIPv4Netmask) TEST_F(NetTest, TestIPv4Netmask)
{ {
ASSERT_TRUE(llarp::xhtonl(llarp::netmask_ipv4_bits(8)) ASSERT_TRUE(llarp::xhtonl(llarp::netmask_ipv4_bits(8))