ipv4 bogon checking

This commit is contained in:
Jeff Becker 2018-10-15 08:02:32 -04:00
parent ca01daa89a
commit d3278946f2
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
11 changed files with 167 additions and 38 deletions

View File

@ -272,9 +272,9 @@ main(int argc, char *argv[])
std::cout << "failed to read " << rcfname << std::endl;
return 1;
}
if(!rc.VerifySignature(&crypto))
if(!rc.Verify(&crypto))
{
std::cout << rcfname << " has invalid signature" << std::endl;
std::cout << rcfname << " is invalid" << std::endl;
return 1;
}
if(!rc.IsPublicRouter())
@ -369,9 +369,9 @@ main(int argc, char *argv[])
return 1;
}
if(!rc.VerifySignature(&crypto))
if(!rc.Verify(&crypto))
{
std::cout << rcfname << " has invalid signature" << std::endl;
std::cout << rcfname << " is invalid" << std::endl;
return 1;
}

View File

@ -7,6 +7,8 @@
#include "logger.hpp"
#include "mem.hpp"
#include <vector>
#include <stdlib.h> // for itoa
// for addrinfo
@ -63,6 +65,9 @@ namespace llarp
operator &(huint32_t x) const { return huint32_t{uint32_t(h & x.h)}; }
constexpr huint32_t
operator |(huint32_t x) const { return huint32_t{uint32_t(h | x.h)}; }
constexpr huint32_t
operator ^(huint32_t x) const { return huint32_t{uint32_t(h ^ x.h)}; }
constexpr huint32_t
operator ~() const { return huint32_t{uint32_t(~h)}; }
@ -71,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; }
struct Hash
{
inline size_t
@ -90,6 +95,9 @@ namespace llarp
operator &(nuint32_t x) const { return nuint32_t{uint32_t(n & x.n)}; }
constexpr nuint32_t
operator |(nuint32_t x) const { return nuint32_t{uint32_t(n | x.n)}; }
constexpr nuint32_t
operator ^(nuint32_t x) const { return nuint32_t{uint32_t(n ^ x.n)}; }
constexpr nuint32_t
operator ~() const { return nuint32_t{uint32_t(~n)}; }
@ -189,6 +197,69 @@ namespace llarp
return huint16_t{ntohs(x.n)};
}
struct IPRange
{
huint32_t addr;
huint32_t netmask_bits;
/// return true if ip is contained in this ip range
bool
Contains(const huint32_t& ip) const
{
// TODO: do this "better"
return ((addr & netmask_bits) ^ ip) == (ip & (~netmask_bits));
}
std::string
ToString() const
{
char strbuf[32] = {0};
char netbuf[32] = {0};
inet_ntop(AF_INET, &addr, strbuf, sizeof(strbuf));
inet_ntop(AF_INET, &netmask_bits, netbuf, sizeof(netbuf));
return std::string(strbuf) + "/" + std::string(netbuf);
}
};
constexpr huint32_t
netmask_ipv4_bits(byte_t netmask)
{
return (32 - netmask) ? (huint32_t{((uint32_t)1 << (32 - (netmask + 1)))}
| netmask_ipv4_bits(netmask + 1))
: huint32_t{0};
}
constexpr huint32_t
ipaddr_ipv4_bits(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
return huint32_t{(a << 24) | (b << 16) | (c << 8) | d};
}
constexpr IPRange
iprange_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask)
{
return IPRange{ipaddr_ipv4_bits(a, b, c, d), netmask_ipv4_bits(mask)};
}
bool
IsIPv4Bogon(const huint32_t& addr);
constexpr bool
ipv6_is_siit(const in6_addr& addr)
{
return addr.s6_addr[11] == 0xff && addr.s6_addr[10] == 0xff
&& addr.s6_addr[9] == 0 && addr.s6_addr[8] == 0 && addr.s6_addr[7] == 0
&& addr.s6_addr[6] == 0 && addr.s6_addr[5] == 0 && addr.s6_addr[4] == 0
&& addr.s6_addr[3] == 0 && addr.s6_addr[2] == 0 && addr.s6_addr[1] == 0
&& addr.s6_addr[0] == 0;
}
bool
IsBogon(const in6_addr& addr);
bool
IsBogonRange(const in6_addr& host, const in6_addr& mask);
struct Addr
{
// network order
@ -355,11 +426,7 @@ namespace llarp
{
memcpy(addr6(), other.ip.s6_addr, 16);
_addr.sin6_port = htons(other.port);
auto ptr = &_addr.sin6_addr.s6_addr[0];
// TODO: detect SIIT better
if(ptr[11] == 0xff && ptr[10] == 0xff && ptr[9] == 0 && ptr[8] == 0
&& ptr[7] == 0 && ptr[6] == 0 && ptr[5] == 0 && ptr[4] == 0
&& ptr[3] == 0 && ptr[2] == 0 && ptr[1] == 0 && ptr[0] == 0)
if(ipv6_is_siit(other.ip))
{
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(other.port);
@ -646,6 +713,14 @@ namespace llarp
return byte1 == 192 && byte2 == 168;
}
/// return true if our ipv4 address is a bogon
/// TODO: ipv6
bool
IsBogon() const
{
return IsIPv4Bogon(xtohl());
}
socklen_t
SockLen() const
{
@ -655,13 +730,10 @@ namespace llarp
return sizeof(sockaddr_in6);
}
// Neuro: can't const this, not sure why...
bool
isPrivate()
isPrivate() const
{
uint32_t byte = this->getHostLong();
return this->isTenPrivate(byte) || this->isOneSevenPrivate(byte)
|| this->isOneNinePrivate(byte);
return IsBogon();
}
bool
@ -683,7 +755,7 @@ namespace llarp
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
}
};
};
}; // namespace llarp
bool
AllInterfaces(int af, Addr& addr);

View File

@ -79,7 +79,7 @@ namespace llarp
SetNick(const std::string &nick);
bool
VerifySignature(llarp_crypto *crypto) const;
Verify(llarp_crypto *crypto) const;
bool
Sign(llarp_crypto *crypto, const llarp::SecretKey &secret);
@ -95,6 +95,10 @@ namespace llarp
bool
Write(const char *fname) const;
private:
bool
VerifySignature(llarp_crypto *crypto) const;
};
} // namespace llarp

View File

@ -665,9 +665,9 @@ namespace llarp
bool
Validate(const RouterContact &rc) const
{
if(!rc.VerifySignature(parent->Crypto()))
if(!rc.Verify(parent->Crypto()))
{
llarp::LogWarn("rc has invalid signature from lookup result");
llarp::LogWarn("rc from lookup result is invalid");
return false;
}
return true;

View File

@ -178,14 +178,6 @@ namespace llarp
#endif
}
constexpr huint32_t
netmask_ipv4_bits(uint32_t netmask)
{
return (32 - netmask) ? (huint32_t{((uint32_t)1 << (32 - (netmask + 1)))}
| netmask_ipv4_bits(netmask + 1))
: huint32_t{0};
}
bool
TunEndpoint::SetupTun()
{

View File

@ -688,7 +688,7 @@ namespace llarp
// build our RC
LinkIntroMessage msg;
msg.rc = Router()->rc();
if(!msg.rc.VerifySignature(&Router()->crypto))
if(!msg.rc.Verify(&Router()->crypto))
{
llarp::LogError("our RC is invalid? closing session to", remoteAddr);
Close();

View File

@ -152,10 +152,10 @@ namespace llarp
llarp::LogError("outer signature failure");
return false;
}
// rc signature
if(!rc.VerifySignature(c))
// verify RC
if(!rc.Verify(c))
{
llarp::LogError("inner signature failure");
llarp::LogError("invalid RC in link intro");
return false;
}
return true;

View File

@ -982,4 +982,45 @@ namespace llarp
return false;
}
bool
IsBogon(const in6_addr& addr)
{
if(!ipv6_is_siit(addr))
return false;
return IsIPv4Bogon(ipaddr_ipv4_bits(addr.s6_addr[12], addr.s6_addr[13],
addr.s6_addr[14], addr.s6_addr[15]));
}
bool
IsBogonRange(const in6_addr& host, const in6_addr& netmask)
{
// TODO: implement me
return true;
}
bool
IsIPv4Bogon(const huint32_t& addr)
{
static std::vector< IPRange > bogonRanges = {
iprange_ipv4(0, 0, 0, 0, 8), iprange_ipv4(10, 0, 0, 0, 8),
iprange_ipv4(21, 0, 0, 0, 8), iprange_ipv4(100, 64, 0, 0, 10),
iprange_ipv4(127, 0, 0, 0, 8), iprange_ipv4(169, 254, 0, 0, 8),
iprange_ipv4(172, 16, 0, 0, 12), iprange_ipv4(192, 0, 0, 0, 24),
iprange_ipv4(192, 0, 2, 0, 24), iprange_ipv4(192, 88, 99, 0, 24),
iprange_ipv4(192, 168, 0, 0, 16), iprange_ipv4(198, 18, 0, 0, 15),
iprange_ipv4(198, 51, 100, 0, 24), iprange_ipv4(203, 0, 113, 0, 24),
iprange_ipv4(224, 0, 0, 0, 4), iprange_ipv4(240, 0, 0, 0, 4)};
for(const auto& bogon : bogonRanges)
{
if(bogon.Contains(addr))
{
char strbuf[32] = {0};
inet_ntop(AF_INET, &addr, strbuf, sizeof(strbuf));
llarp::LogError("bogon: ", strbuf, " in ", bogon.ToString());
return true;
}
}
return false;
}
} // namespace llarp

View File

@ -156,9 +156,9 @@ struct llarp_nodedb
llarp::LogError("failed to read file ", fpath);
return false;
}
if(!rc.VerifySignature(crypto))
if(!rc.Verify(crypto))
{
llarp::LogError("Signature verify failed", fpath);
llarp::LogError(fpath, " contains invalid RC");
return false;
}
{
@ -243,7 +243,7 @@ crypto_threadworker_verifyrc(void *user)
llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user);
llarp::RouterContact rc = verify_request->rc;
verify_request->valid = rc.VerifySignature(verify_request->nodedb->crypto);
verify_request->valid = rc.Verify(verify_request->nodedb->crypto);
// if it's valid we need to set it
if(verify_request->valid && rc.IsPublicRouter())
{

View File

@ -252,7 +252,7 @@ llarp_router::try_connect(fs::path rcfile)
llarp::LogError("failure to decode or verify of remote RC");
return;
}
if(remote.VerifySignature(&crypto))
if(remote.Verify(&crypto))
{
llarp::LogDebug("verified signature");
// store into filesystem
@ -267,7 +267,7 @@ llarp_router::try_connect(fs::path rcfile)
}
}
else
llarp::LogError("failed to verify signature of RC ", rcfile);
llarp::LogError(rcfile, " contains invalid RC");
}
bool
@ -302,10 +302,10 @@ bool
llarp_router::SaveRC()
{
llarp::LogDebug("verify RC signature");
if(!rc().VerifySignature(&crypto))
if(!rc().Verify(&crypto))
{
rc().Dump< MAX_RC_SIZE >();
llarp::LogError("RC has bad signature not saving");
llarp::LogError("RC is invalid, not saving");
return false;
}
return rc().Write(our_rc_file.string().c_str());

View File

@ -3,6 +3,7 @@
#include <llarp/version.h>
#include <llarp/crypto.hpp>
#include <llarp/time.h>
#include <llarp/net.hpp>
#include "buffer.hpp"
#include "logger.hpp"
#include "mem.hpp"
@ -163,6 +164,25 @@ namespace llarp
return crypto->sign(signature, secretkey, buf);
}
bool
RouterContact::Verify(llarp_crypto *crypto) const
{
for(const auto &a : addrs)
{
if(IsBogon(a.ip))
{
llarp::LogError("invalid address info: ", a);
return false;
}
}
for(const auto &exit : exits)
{
if(IsBogonRange(exit.address, exit.netmask))
return false;
}
return VerifySignature(crypto);
}
bool
RouterContact::VerifySignature(llarp_crypto *crypto) const
{