initial v6 exits

pull/1538/head
Jeff Becker 3 years ago
parent fe29df696c
commit bd93a8f828
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -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…
Cancel
Save