mirror of https://github.com/oxen-io/lokinet
initial v6 exits
This commit is contained in:
parent
fe29df696c
commit
bd93a8f828
|
@ -68,12 +68,14 @@ main(int argc, char* argv[])
|
|||
("token", "exit auth token to use", cxxopts::value<std::string>())
|
||||
("auth", "exit auth token to use", cxxopts::value<std::string>())
|
||||
("status", "print status and exit", cxxopts::value<bool>())
|
||||
("range", "ip range to map", cxxopts::value<std::string>())
|
||||
;
|
||||
// clang-format on
|
||||
lokimq::address rpcURL("tcp://127.0.0.1:1190");
|
||||
std::string exitAddress;
|
||||
std::string endpoint = "default";
|
||||
std::optional<std::string> token;
|
||||
std::string range = "::/0";
|
||||
lokimq::LogLevel logLevel = lokimq::LogLevel::warn;
|
||||
bool goUp = false;
|
||||
bool goDown = false;
|
||||
|
@ -118,6 +120,10 @@ main(int argc, char* argv[])
|
|||
{
|
||||
token = result["auth"].as<std::string>();
|
||||
}
|
||||
if (result.count("range") > 0)
|
||||
{
|
||||
range = result["range"].as<std::string>();
|
||||
}
|
||||
}
|
||||
catch (const cxxopts::option_not_exists_exception& ex)
|
||||
{
|
||||
|
@ -216,12 +222,12 @@ main(int argc, char* argv[])
|
|||
lmq,
|
||||
connID,
|
||||
"llarp.exit",
|
||||
nlohmann::json{{"exit", exitAddress}, {"range", "0.0.0.0/0"}, {"token", *token}});
|
||||
nlohmann::json{{"exit", exitAddress}, {"range", range}, {"token", *token}});
|
||||
}
|
||||
else
|
||||
{
|
||||
maybe_result = LMQ_Request(
|
||||
lmq, connID, "llarp.exit", nlohmann::json{{"exit", exitAddress}, {"range", "0.0.0.0/0"}});
|
||||
lmq, connID, "llarp.exit", nlohmann::json{{"exit", exitAddress}, {"range", range}});
|
||||
}
|
||||
|
||||
if (not maybe_result.has_value())
|
||||
|
@ -238,7 +244,7 @@ main(int argc, char* argv[])
|
|||
}
|
||||
if (goDown)
|
||||
{
|
||||
LMQ_Request(lmq, connID, "llarp.exit", nlohmann::json{{"range", "0.0.0.0/0"}, {"unmap", true}});
|
||||
LMQ_Request(lmq, connID, "llarp.exit", nlohmann::json{{"range", range}, {"unmap", true}});
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -182,8 +182,9 @@ namespace llarp
|
|||
}
|
||||
m_OurRange = *maybe;
|
||||
}
|
||||
|
||||
m_OurIP = m_OurRange.addr;
|
||||
m_UseV6 = not m_OurRange.IsV4();
|
||||
m_UseV6 = false;
|
||||
return Endpoint::Configure(conf, dnsConf);
|
||||
}
|
||||
|
||||
|
@ -707,6 +708,11 @@ namespace llarp
|
|||
|
||||
vpn::InterfaceInfo info;
|
||||
info.addrs.emplace(m_OurRange);
|
||||
IPRange v6range = m_OurRange;
|
||||
v6range.addr = net::ExpandV4Lan(net::TruncateV6(m_OurRange.addr));
|
||||
LogInfo(Name(), " using v6 range: ", v6range);
|
||||
info.addrs.emplace(v6range, AF_INET6);
|
||||
|
||||
info.ifname = m_IfName;
|
||||
info.dnsaddr.FromString(m_LocalResolverAddr.toHost());
|
||||
|
||||
|
@ -736,6 +742,13 @@ namespace llarp
|
|||
return false;
|
||||
}
|
||||
|
||||
const auto maybe = GetInterfaceIP6(m_IfName);
|
||||
if (maybe.has_value())
|
||||
{
|
||||
m_OurIP6 = *maybe;
|
||||
LogInfo(Name(), " has ipv6 address ", m_OurIP6);
|
||||
}
|
||||
|
||||
netloop->add_ticker([&]() { Flush(); });
|
||||
|
||||
if (m_OnUp)
|
||||
|
@ -826,7 +839,10 @@ namespace llarp
|
|||
}
|
||||
|
||||
*/
|
||||
|
||||
if (m_state->m_ExitEnabled)
|
||||
{
|
||||
dst = net::ExpandV4(net::TruncateV6(dst));
|
||||
}
|
||||
auto itr = m_IPToAddr.find(dst);
|
||||
if (itr == m_IPToAddr.end())
|
||||
{
|
||||
|
@ -843,8 +859,7 @@ namespace llarp
|
|||
else
|
||||
{
|
||||
const auto addr = *exits.begin();
|
||||
if (pkt.IsV4())
|
||||
pkt.ZeroSourceAddress();
|
||||
pkt.ZeroSourceAddress();
|
||||
MarkAddressOutbound(addr);
|
||||
EnsurePathToService(
|
||||
addr,
|
||||
|
@ -934,7 +949,10 @@ namespace llarp
|
|||
if (pkt.IsV4())
|
||||
dst = pkt.dst4to6Lan();
|
||||
else if (pkt.IsV6())
|
||||
{
|
||||
dst = pkt.dstv6();
|
||||
src = net::ExpandV4Lan(net::TruncateV6(src));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -948,11 +966,11 @@ namespace llarp
|
|||
if (pkt.IsV4())
|
||||
{
|
||||
dst = m_OurIP;
|
||||
src = pkt.src4to6();
|
||||
src = pkt.src4to6Lan();
|
||||
}
|
||||
else if (pkt.IsV6())
|
||||
{
|
||||
dst = pkt.dstv6();
|
||||
dst = m_OurIP6;
|
||||
src = pkt.srcv6();
|
||||
}
|
||||
// find what exit we think this should be for
|
||||
|
|
|
@ -235,6 +235,9 @@ namespace llarp
|
|||
std::unordered_map<huint128_t, llarp_time_t> m_IPActivity;
|
||||
/// our ip address (host byte order)
|
||||
huint128_t m_OurIP;
|
||||
/// our ip for ip6
|
||||
huint128_t m_OurIP6;
|
||||
|
||||
/// next ip address to allocate (host byte order)
|
||||
huint128_t m_NextIP;
|
||||
/// highest ip address to allocate (host byte order)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace llarp::net
|
|||
constexpr huint128_t
|
||||
ExpandV4Lan(huint32_t x)
|
||||
{
|
||||
return huint128_t{uint128_t{0xfe80'0000'0000'0000UL, 0UL}} | huint128_t{x.h};
|
||||
return huint128_t{uint128_t{0xfd00'0000'0000'0000UL, 0UL}} | huint128_t{x.h};
|
||||
}
|
||||
|
||||
constexpr huint32_t
|
||||
|
|
|
@ -161,6 +161,14 @@ namespace llarp
|
|||
return ip;
|
||||
}
|
||||
|
||||
huint128_t
|
||||
IpAddress::toIP6() const
|
||||
{
|
||||
huint128_t ip;
|
||||
ip.FromString(m_ipAddress);
|
||||
return ip;
|
||||
}
|
||||
|
||||
bool
|
||||
IpAddress::operator<(const IpAddress& other) const
|
||||
{
|
||||
|
|
|
@ -126,6 +126,9 @@ namespace llarp
|
|||
huint32_t
|
||||
toIP() const;
|
||||
|
||||
huint128_t
|
||||
toIP6() const;
|
||||
|
||||
// TODO: other utility functions left over from Addr which may be useful
|
||||
// IsBogon() const;
|
||||
// isPrivate() const;
|
||||
|
|
|
@ -550,12 +550,25 @@ namespace llarp
|
|||
{
|
||||
sockaddr_storage s;
|
||||
sockaddr* sptr = (sockaddr*)&s;
|
||||
sptr->sa_family = af;
|
||||
if (!llarp_getifaddr(ifname.c_str(), af, sptr))
|
||||
return std::nullopt;
|
||||
llarp::SockAddr saddr = SockAddr(*sptr);
|
||||
llarp::SockAddr saddr = SockAddr{*sptr};
|
||||
return llarp::IpAddress(saddr);
|
||||
}
|
||||
|
||||
std::optional<huint128_t>
|
||||
GetInterfaceIP6(std::string ifname)
|
||||
{
|
||||
sockaddr_storage s;
|
||||
sockaddr* sptr = (sockaddr*)&s;
|
||||
sptr->sa_family = AF_INET6;
|
||||
if (!llarp_getifaddr(ifname.c_str(), AF_INET6, sptr))
|
||||
return std::nullopt;
|
||||
llarp::SockAddr addr{*sptr};
|
||||
return addr.asIPv6();
|
||||
}
|
||||
|
||||
bool
|
||||
AllInterfaces(int af, IpAddress& result)
|
||||
{
|
||||
|
|
|
@ -77,6 +77,10 @@ namespace llarp
|
|||
std::optional<IpAddress>
|
||||
GetIFAddr(const std::string& ifname, int af = AF_INET);
|
||||
|
||||
/// get an interface's ip6 address
|
||||
std::optional<huint128_t>
|
||||
GetInterfaceIP6(std::string ifname);
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -178,8 +178,19 @@ namespace llarp::net
|
|||
}
|
||||
if (mode == GatewayMode::eUpperDefault)
|
||||
{
|
||||
rtattr_add(
|
||||
&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, sizeof(uint32_t));
|
||||
if (dst->family == AF_INET)
|
||||
{
|
||||
rtattr_add(
|
||||
&nl_request.n,
|
||||
sizeof(nl_request),
|
||||
/*RTA_NEWDST*/ RTA_DST,
|
||||
&dst->data,
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, 16);
|
||||
}
|
||||
}
|
||||
/* Send message to the netlink */
|
||||
return send(sock, &nl_request, sizeof(nl_request), 0);
|
||||
|
@ -191,7 +202,7 @@ namespace llarp::net
|
|||
if (strchr(addr, ':'))
|
||||
{
|
||||
res->family = AF_INET6;
|
||||
res->bitlen = 128;
|
||||
res->bitlen = bitlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -335,7 +346,7 @@ namespace llarp::net
|
|||
int if_idx = if_nametoindex(ifname.c_str());
|
||||
_inet_addr to_addr{};
|
||||
_inet_addr gw_addr{};
|
||||
const auto maybe = GetIFAddr(ifname);
|
||||
auto maybe = GetIFAddr(ifname);
|
||||
if (not maybe.has_value())
|
||||
throw std::runtime_error("we dont have our own net interface?");
|
||||
int nl_cmd = RTM_NEWROUTE;
|
||||
|
@ -345,6 +356,21 @@ namespace llarp::net
|
|||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
|
||||
read_addr("128.0.0.0", &to_addr, 1);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
const auto maybeInt = GetInterfaceIP6(ifname);
|
||||
if (maybeInt.has_value())
|
||||
{
|
||||
const auto host = maybeInt->ToString();
|
||||
LogInfo("add v6 route via ", host);
|
||||
read_addr(host.c_str(), &gw_addr, 128);
|
||||
read_addr("::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
|
||||
read_addr("4000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
read_addr("8000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
read_addr("c000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
}
|
||||
#endif
|
||||
#elif _WIN32
|
||||
// poke hole for loopback bacause god is dead on windows
|
||||
|
@ -370,7 +396,7 @@ namespace llarp::net
|
|||
int if_idx = if_nametoindex(ifname.c_str());
|
||||
_inet_addr to_addr{};
|
||||
_inet_addr gw_addr{};
|
||||
const auto maybe = GetIFAddr(ifname);
|
||||
auto maybe = GetIFAddr(ifname);
|
||||
|
||||
if (not maybe.has_value())
|
||||
throw std::runtime_error("we dont have our own net interface?");
|
||||
|
@ -381,6 +407,22 @@ namespace llarp::net
|
|||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
|
||||
read_addr("128.0.0.0", &to_addr, 1);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
|
||||
const auto maybeInt = GetInterfaceIP6(ifname);
|
||||
if (maybeInt.has_value())
|
||||
{
|
||||
const auto host = maybeInt->ToString();
|
||||
LogInfo("del v6 route via ", host);
|
||||
read_addr(host.c_str(), &gw_addr, 128);
|
||||
read_addr("::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx);
|
||||
read_addr("4000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
read_addr("8000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
read_addr("c000::", &to_addr, 2);
|
||||
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx);
|
||||
}
|
||||
#endif
|
||||
#elif _WIN32
|
||||
ifname.back()++;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <net/sock_addr.hpp>
|
||||
#include <net/ip.hpp>
|
||||
#include <net/net_bits.hpp>
|
||||
#include <util/str.hpp>
|
||||
#include <util/logging/logger.hpp>
|
||||
|
@ -187,6 +188,12 @@ namespace llarp
|
|||
sizeof(m_addr.sin6_addr.s6_addr)));
|
||||
}
|
||||
|
||||
huint128_t
|
||||
SockAddr::asIPv6() const
|
||||
{
|
||||
return net::In6ToHUInt(m_addr.sin6_addr);
|
||||
}
|
||||
|
||||
void
|
||||
SockAddr::fromString(std::string_view str)
|
||||
{
|
||||
|
@ -204,7 +211,12 @@ namespace llarp
|
|||
// TODO: having ":port" at the end makes this ambiguous with IPv6
|
||||
// come up with a strategy for implementing
|
||||
if (splits.size() > 2)
|
||||
throw std::runtime_error("IPv6 not yet supported");
|
||||
{
|
||||
std::string data{str};
|
||||
if (inet_pton(AF_INET6, data.c_str(), m_addr.sin6_addr.s6_addr) == -1)
|
||||
throw std::runtime_error{"invalid ip6 address: " + data};
|
||||
return;
|
||||
}
|
||||
|
||||
// split() shouldn't return an empty list if str is empty (checked above)
|
||||
assert(splits.size() > 0);
|
||||
|
|
|
@ -16,6 +16,7 @@ inet_pton(int af, const char* src, void* dst);
|
|||
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <net/net_int.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -80,6 +81,9 @@ namespace llarp
|
|||
uint16_t
|
||||
getPort() const;
|
||||
|
||||
huint128_t
|
||||
asIPv6() const;
|
||||
|
||||
private:
|
||||
bool m_empty = true;
|
||||
sockaddr_in6 m_addr;
|
||||
|
|
|
@ -131,8 +131,7 @@ namespace llarp
|
|||
DisableAllRoutes();
|
||||
EnableAllRoutes();
|
||||
|
||||
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
||||
net::AddDefaultRouteViaInterface(ep->GetIfName());
|
||||
Up();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,4 +155,27 @@ namespace llarp
|
|||
|
||||
DisableAllRoutes();
|
||||
}
|
||||
|
||||
void
|
||||
RoutePoker::Up()
|
||||
{
|
||||
// explicit route pokes for first hops
|
||||
m_Router->ForEachPeer(
|
||||
[&](auto session, auto) mutable { AddRoute(session->GetRemoteEndpoint().toIP()); }, false);
|
||||
// add default route
|
||||
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
||||
net::AddDefaultRouteViaInterface(ep->GetIfName());
|
||||
}
|
||||
|
||||
void
|
||||
RoutePoker::Down()
|
||||
{
|
||||
// unpoke routes for first hops
|
||||
m_Router->ForEachPeer(
|
||||
[&](auto session, auto) mutable { DelRoute(session->GetRemoteEndpoint().toIP()); }, false);
|
||||
// remove default route
|
||||
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
||||
net::DelDefaultRouteViaInterface(ep->GetIfName());
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <net/net_int.hpp>
|
||||
|
||||
namespace llarp
|
||||
|
@ -34,6 +35,14 @@ namespace llarp
|
|||
void
|
||||
Disable();
|
||||
|
||||
/// explicitly put routes up
|
||||
void
|
||||
Up();
|
||||
|
||||
/// explicitly put routes down
|
||||
void
|
||||
Down();
|
||||
|
||||
private:
|
||||
void
|
||||
DeleteAllRoutes();
|
||||
|
|
|
@ -156,7 +156,6 @@ namespace llarp::rpc
|
|||
{
|
||||
map = false;
|
||||
}
|
||||
|
||||
const auto range_itr = obj.find("range");
|
||||
if (range_itr == obj.end())
|
||||
{
|
||||
|
@ -204,13 +203,7 @@ namespace llarp::rpc
|
|||
reply(CreateJSONError("could not find exit"));
|
||||
return;
|
||||
}
|
||||
r->ForEachPeer(
|
||||
[r](auto session, auto) mutable {
|
||||
const auto ip = session->GetRemoteEndpoint().toIP();
|
||||
r->routePoker().AddRoute(ip);
|
||||
},
|
||||
false);
|
||||
net::AddDefaultRouteViaInterface(ep->GetIfName());
|
||||
r->routePoker().Up();
|
||||
reply(CreateJSONResponse("OK"));
|
||||
},
|
||||
5s);
|
||||
|
@ -250,14 +243,7 @@ namespace llarp::rpc
|
|||
}
|
||||
else if (not map)
|
||||
{
|
||||
net::DelDefaultRouteViaInterface(ep->GetIfName());
|
||||
|
||||
r->ForEachPeer(
|
||||
[r](auto session, auto) mutable {
|
||||
const auto ip = session->GetRemoteEndpoint().toIP();
|
||||
r->routePoker().DelRoute(ip);
|
||||
},
|
||||
false);
|
||||
r->routePoker().Down();
|
||||
ep->UnmapExitRange(range);
|
||||
}
|
||||
reply(CreateJSONResponse("OK"));
|
||||
|
|
Loading…
Reference in New Issue