Skip to content

Commit

Permalink
set source ip on service nodes for outbound link to not use all inter…
Browse files Browse the repository at this point in the history
…faces
  • Loading branch information
majestrate committed May 27, 2022
1 parent 60ada47 commit 98b3860
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 68 deletions.
38 changes: 14 additions & 24 deletions llarp/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,32 +126,23 @@ namespace llarp
"provided the public-port option must also be specified.",
},
[this](std::string arg) {
if (not arg.empty())
{
llarp::LogInfo("public ip ", arg, " size ", arg.size());
if (arg.empty())
return;
nuint32_t addr{};
if (not addr.FromString(arg))
throw std::invalid_argument{stringify(arg, " is not a valid IPv4 address")};

if (arg.size() > 15)
throw std::invalid_argument(stringify("Not a valid IPv4 addr: ", arg));
if (IsIPv4Bogon(addr))
throw std::invalid_argument{
stringify(addr, " looks like it is not a publicly routable ip address")};

m_publicAddress.setAddress(arg);
}
m_PublicIP = addr;
});

conf.defineOption<std::string>("router", "public-address", Hidden, [this](std::string arg) {
if (not arg.empty())
{
llarp::LogWarn(
"*** WARNING: The config option [router]:public-address=",
arg,
" is deprecated, use public-ip=",
arg,
" instead to avoid this warning and avoid future configuration problems.");

if (arg.size() > 15)
throw std::invalid_argument(stringify("Not a valid IPv4 addr: ", arg));

m_publicAddress.setAddress(arg);
}
conf.defineOption<std::string>("router", "public-address", Hidden, [](std::string) {
throw std::invalid_argument{
"[router]:public-address option no longer supported, use [router]:public-ip and "
"[router]:public-port instead"};
});

conf.defineOption<int>(
Expand All @@ -166,8 +157,7 @@ namespace llarp
[this](int arg) {
if (arg <= 0 || arg > std::numeric_limits<uint16_t>::max())
throw std::invalid_argument("public-port must be >= 0 and <= 65536");

m_publicAddress.setPort(arg);
m_PublicPort = ToNet(huint16_t{static_cast<uint16_t>(arg)});
});

conf.defineOption<int>(
Expand Down
3 changes: 2 additions & 1 deletion llarp/config/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ namespace llarp

bool m_blockBogons = false;

IpAddress m_publicAddress;
std::optional<nuint32_t> m_PublicIP;
nuint16_t m_PublicPort;

int m_workerThreads = -1;
int m_numNetThreads = -1;
Expand Down
43 changes: 38 additions & 5 deletions llarp/link/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <utility>
#include <unordered_set>
#include <llarp/router/abstractrouter.hpp>
#include <oxenc/variant.h>

static constexpr auto LINK_LAYER_TICK_INTERVAL = 100ms;

Expand Down Expand Up @@ -129,7 +130,7 @@ namespace llarp
}

bool
ILinkLayer::Configure(AbstractRouter* router, const std::string& ifname, int af, uint16_t port)
ILinkLayer::Configure(AbstractRouter* router, std::string ifname, int af, uint16_t port)
{
m_Router = router;
m_udp = m_Router->loop()->make_udp(
Expand All @@ -142,11 +143,42 @@ namespace llarp

if (ifname == "*")
{
if (!AllInterfaces(af, m_ourAddr))
if (router->IsServiceNode())
{
if (auto maybe = router->OurPublicIP())
{
auto addr = var::visit([](auto&& addr) { return SockAddr{addr}; }, *maybe);
// service node outbound link
if (HasInterfaceAddress(addr.getIP()))
{
// we have our ip claimed on a local net interface
m_ourAddr = addr;
}
else if (auto maybe = net::AllInterfaces(addr))
{
// we do not have our claimed ip, nat or something?
m_ourAddr = *maybe;
}
else
return false; // the ultimate failure case
}
else
return false;
}
else if (auto maybe = net::AllInterfaces(SockAddr{"0.0.0.0"}))
{
// client outbound link
m_ourAddr = *maybe;
}
else
return false;
}
else
{
if (ifname == "0.0.0.0" and not GetBestNetIF(ifname))
throw std::invalid_argument{
"0.0.0.0 provided and we cannot find a valid ip to use, please set one "
"explicitly instead in the bind section instead of 0.0.0.0"};
if (const auto maybe = GetInterfaceAddr(ifname, af))
{
m_ourAddr = *maybe;
Expand All @@ -157,10 +189,11 @@ namespace llarp
{
m_ourAddr = SockAddr{ifname + ":0"};
}
catch (const std::exception& e)
catch (const std::exception& ex)
{
LogError(stringify("Could not use ifname ", ifname, " to configure ILinkLayer"));
throw e;
LogError(
stringify("Could not use ifname ", ifname, " to configure ILinkLayer: ", ex.what()));
throw ex;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion llarp/link/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace llarp
SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt);

virtual bool
Configure(AbstractRouter* loop, const std::string& ifname, int af, uint16_t port);
Configure(AbstractRouter* loop, std::string ifname, int af, uint16_t port);

virtual std::shared_ptr<ILinkSession>
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;
Expand Down
6 changes: 6 additions & 0 deletions llarp/net/address_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ namespace llarp
return lhs.rank < rhs.rank || lhs.ip < rhs.ip || lhs.port < rhs.port;
}

std::variant<nuint32_t, nuint128_t>
AddressInfo::IP() const
{
return SockAddr{ip}.getIP();
}

bool
AddressInfo::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf)
{
Expand Down
6 changes: 6 additions & 0 deletions llarp/net/address_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <string>
#include <vector>

#include <oxenc/variant.h>

/**
* address_info.hpp
*
Expand Down Expand Up @@ -47,6 +49,10 @@ namespace llarp
void
fromSockAddr(const SockAddr& address);

/// get this as an explicit v4 or explicit v6
std::variant<nuint32_t, nuint128_t>
IP() const;

std::ostream&
print(std::ostream& stream, int level, int spaces) const;
};
Expand Down
80 changes: 61 additions & 19 deletions llarp/net/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,29 +576,56 @@ namespace llarp
return addr.asIPv6();
}

bool
AllInterfaces(int af, SockAddr& result)
namespace net
{
if (af == AF_INET)
namespace
{
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
result = SockAddr{addr};
return true;
}
if (af == AF_INET6)
SockAddr
All(int af)
{
if (af == AF_INET)
{
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
return SockAddr{addr};
}
sockaddr_in6 addr6{};
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(0);
addr6.sin6_addr = IN6ADDR_ANY_INIT;
return SockAddr{addr6};
}
} // namespace

std::optional<SockAddr>
AllInterfaces(SockAddr pub)
{
sockaddr_in6 addr6;
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(0);
addr6.sin6_addr = IN6ADDR_ANY_INIT;
result = SockAddr{addr6};
return true;
std::optional<SockAddr> found;
IterAllNetworkInterfaces([pub, &found](auto* ifa) {
if (found)
return;
if (auto ifa_addr = ifa->ifa_addr)
{
if (ifa_addr->sa_family != pub.Family())
return;

SockAddr addr{*ifa->ifa_addr};

if (addr == pub)
found = addr;
}
});

// 0.0.0.0 is used in our compat shim as our public ip so we check for that special case
const auto zero = IPRange::FromIPv4(0, 0, 0, 0, 8);
// when we cannot find an address but we are looking for 0.0.0.0 just default to the old style
if (not found and (pub.isIPv4() and zero.Contains(pub.asIPv4())))
found = All(pub.Family());
return found;
}
return false;
}
} // namespace net

#if !defined(TESTNET)
static constexpr std::array bogonRanges_v6 = {
Expand Down Expand Up @@ -692,5 +719,20 @@ namespace llarp
return false;
}
#endif
bool
HasInterfaceAddress(std::variant<nuint32_t, nuint128_t> ip)
{
bool found{false};
IterAllNetworkInterfaces([ip, &found](const auto* iface) {
if (found or iface == nullptr)
return;
if (auto addr = iface->ifa_addr;
addr and (addr->sa_family == AF_INET or addr->sa_family == AF_INET6))
{
found = SockAddr{*iface->ifa_addr}.getIP() == ip;
}
});
return found;
}

} // namespace llarp
31 changes: 29 additions & 2 deletions llarp/net/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ namespace llarp
bool
IsIPv4Bogon(const huint32_t& addr);

inline bool
IsIPv4Bogon(const nuint32_t& addr)
{
return IsIPv4Bogon(ToHost(addr));
}

bool
IsBogon(const in6_addr& addr);

Expand All @@ -61,8 +67,25 @@ namespace llarp
bool
IsBogonRange(const in6_addr& host, const in6_addr& mask);

bool
AllInterfaces(int af, SockAddr& addr);
/// get a sock addr we can use for all interfaces given our public address
namespace net
{
std::optional<SockAddr>
AllInterfaces(SockAddr pubaddr);
}

/// compat shim
// TODO: remove me
inline bool
AllInterfaces(int af, SockAddr& addr)
{
if (auto maybe = net::AllInterfaces(SockAddr{af == AF_INET ? "0.0.0.0" : "::"}))
{
addr = *maybe;
return true;
}
return false;
}

/// get first network interface with public address
bool
Expand Down Expand Up @@ -92,4 +115,8 @@ namespace llarp
}
#endif

/// return true if we have a network interface with this ip
bool
HasInterfaceAddress(std::variant<nuint32_t, nuint128_t> ip);

} // namespace llarp
8 changes: 8 additions & 0 deletions llarp/net/sock_addr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,14 @@ namespace llarp
return a;
}

std::variant<nuint32_t, nuint128_t>
SockAddr::getIP() const
{
if (isIPv4())
return getIPv4();
return getIPv6();
}

void
SockAddr::setIPv4(nuint32_t ip)
{
Expand Down
11 changes: 11 additions & 0 deletions llarp/net/sock_addr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <string_view>
#include <string>
#include "net_int.hpp"
#include <oxenc/variant.h>

namespace llarp
{
Expand Down Expand Up @@ -81,6 +82,14 @@ namespace llarp
std::string
hostString() const;

inline int
Family() const
{
if (isIPv6())
return AF_INET6;
return AF_INET;
}

/// Returns true if this is an empty SockAddr, defined by having no IP address set. An empty IP
/// address with a valid port is still considered empty.
///
Expand Down Expand Up @@ -133,6 +142,8 @@ namespace llarp
getIPv6() const;
nuint32_t
getIPv4() const;
std::variant<nuint32_t, nuint128_t>
getIP() const;

/// in host order
huint128_t
Expand Down
4 changes: 4 additions & 0 deletions llarp/router/abstractrouter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ namespace llarp
virtual const byte_t*
pubkey() const = 0;

/// get what our real public ip is if we can know it
virtual std::optional<std::variant<nuint32_t, nuint128_t>>
OurPublicIP() const = 0;

/// connect to N random routers
virtual void
ConnectToRandomRouters(int N) = 0;
Expand Down
Loading

0 comments on commit 98b3860

Please sign in to comment.