diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 051d86fae..109823fb3 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -112,6 +112,40 @@ namespace llarp::net return 0; } + struct nl_req + { + struct nlmsghdr n; + struct rtmsg r; + char buf[4096]; + }; + + /// add/remove a route blackhole + int + do_blackhole(int sock, int cmd, int flags, int af) + { + nl_req nl_request{}; + /* Initialize request structure */ + nl_request.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + nl_request.n.nlmsg_flags = NLM_F_REQUEST | flags; + nl_request.n.nlmsg_type = cmd; + nl_request.n.nlmsg_pid = getpid(); + nl_request.r.rtm_family = af; + nl_request.r.rtm_table = RT_TABLE_LOCAL; + nl_request.r.rtm_type = RTN_BLACKHOLE; + nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE; + if (af == AF_INET) + { + uint32_t addr{}; + rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &addr, sizeof(addr)); + } + else + { + uint128_t addr{}; + rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &addr, sizeof(addr)); + } + return send(sock, &nl_request, sizeof(nl_request), 0); + } + int do_route( int sock, @@ -122,12 +156,7 @@ namespace llarp::net GatewayMode mode, int if_idx) { - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[4096]; - } nl_request{}; + nl_req nl_request{}; /* Initialize request structure */ nl_request.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); @@ -360,6 +389,32 @@ namespace llarp::net #endif } + void + AddBlackhole() + { + LogInfo("adding route blackhole to drop all traffic"); +#if __linux__ +#ifndef ANDROID + NLSocket sock; + do_blackhole(sock.fd, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET); + do_blackhole(sock.fd, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET6); +#endif +#endif + } + + void + DelBlackhole() + { + LogInfo("remove route blackhole"); +#if __linux__ +#ifndef ANDROID + NLSocket sock; + do_blackhole(sock.fd, RTM_DELROUTE, 0, AF_INET); + do_blackhole(sock.fd, RTM_DELROUTE, 0, AF_INET6); +#endif +#endif + } + void AddDefaultRouteViaInterface(std::string ifname) { diff --git a/llarp/net/route.hpp b/llarp/net/route.hpp index 6dccbbf23..23e75f8d6 100644 --- a/llarp/net/route.hpp +++ b/llarp/net/route.hpp @@ -25,4 +25,12 @@ namespace llarp::net void DelDefaultRouteViaInterface(std::string ifname); + /// add route blackhole for all traffic + void + AddBlackhole(); + + /// delete route blackhole for all traffic + void + DelBlackhole(); + } // namespace llarp::net diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 29818e840..2d9b1e3ee 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -91,6 +91,7 @@ namespace llarp if (gateway.h) net::DelRoute(ip.ToString(), gateway.ToString()); } + net::DelBlackhole(); } std::optional @@ -185,6 +186,8 @@ namespace llarp void RoutePoker::Up() { + // black hole all routes by default + net::AddBlackhole(); // explicit route pokes for first hops m_Router->ForEachPeer( [&](auto session, auto) mutable { AddRoute(session->GetRemoteEndpoint().asIPv4()); }, @@ -204,6 +207,8 @@ namespace llarp // remove default route const auto ep = m_Router->hiddenServiceContext().GetDefault(); net::DelDefaultRouteViaInterface(ep->GetIfName()); + // delete route blackhole + net::DelBlackhole(); } } // namespace llarp