mirror of https://github.com/oxen-io/lokinet
ipv4 bogon checking
This commit is contained in:
parent
ca01daa89a
commit
d3278946f2
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue