mirror of
https://github.com/google/nsjail.git
synced 2026-08-30 18:41:30 -07:00
Makefile/all: make libnl3 optional
This commit is contained in:
4
Makefile
4
Makefile
@@ -35,7 +35,7 @@ CXXFLAGS += $(USER_DEFINES) $(COMMON_FLAGS) $(PROTOBUF_CFLAGS) -I. \
|
||||
LDFLAGS += -pie -Wl,-z,noexecstack -lpthread $(PROTOBUF_LIBS)
|
||||
|
||||
ifeq ($(NL3_EXISTS), yes)
|
||||
CXXFLAGS += $(shell pkg-config --cflags libnl-route-3.0)
|
||||
CXXFLAGS += $(shell pkg-config --cflags libnl-route-3.0) -DHAVE_LIBNL3
|
||||
LDFLAGS += $(shell pkg-config --libs libnl-route-3.0)
|
||||
endif
|
||||
|
||||
@@ -157,11 +157,13 @@ test: $(BIN)
|
||||
$(call run_test, ./nsjail --config tests/pasta-nat.cfg -q -t 3 -- /bin/bash -c 'sleep 0.2; ping -W 1 -c 1 8.8.8.8 && exit 77', 77)
|
||||
$(call run_test, ./nsjail --config tests/pasta-port-mappings.cfg -q -t 3 -- /bin/bash -c 'sleep 0.2; { netstat -tan | grep LISTEN; } && exit 77', 77)
|
||||
|
||||
ifeq ($(NL3_EXISTS), yes)
|
||||
# --- Traffic rules tests ---
|
||||
$(call run_test, ./nsjail --config tests/traffic-rules.cfg -q -t 1 -- /bin/bash -c 'sleep 10', 137)
|
||||
$(call run_test, ./nsjail --config tests/traffic-drop-tcp4.cfg -q -t 1 -- /bin/bash -c 'sleep 10', 137)
|
||||
$(call run_test, ./nsjail --config tests/traffic-drop-udp6.cfg -q -t 1 -- /bin/bash -c 'sleep 10', 137)
|
||||
$(call run_test, ./nsjail --config tests/traffic-mixed.cfg -q -t 1 -- /bin/bash -c 'sleep 10', 137)
|
||||
endif
|
||||
|
||||
# --- IPv4-only NAT tests ---
|
||||
$(call run_test, ./nsjail --config tests/nat-ip4-only.cfg -q -t 3 --cap CAP_NET_RAW -- /bin/bash -c 'ping -4 -W 1 -c 1 8.8.8.8 && exit 77', 77)
|
||||
|
||||
26
net.cc
26
net.cc
@@ -30,9 +30,11 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef HAVE_LIBNL3
|
||||
#include <netlink/route/nexthop.h>
|
||||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/rule.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -126,10 +128,13 @@ namespace net {
|
||||
#define IFACE_NAME "vs"
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#ifdef HAVE_LIBNL3
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/link/macvlan.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNL3
|
||||
static bool cloneIface(nsj_t* nsj, struct nl_sock* sk, struct nl_cache* link_cache, int pid) {
|
||||
struct rtnl_link* rmv = rtnl_link_macvlan_alloc();
|
||||
if (rmv == nullptr) {
|
||||
@@ -177,7 +182,9 @@ static bool cloneIface(nsj_t* nsj, struct nl_sock* sk, struct nl_cache* link_cac
|
||||
rtnl_link_put(rmv);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNL3
|
||||
static bool moveToNs(
|
||||
const std::string& iface, struct nl_sock* sk, struct nl_cache* link_cache, pid_t pid) {
|
||||
LOG_D("Moving interface '%s' into netns=%d", iface.c_str(), (int)pid);
|
||||
@@ -209,6 +216,7 @@ static bool moveToNs(
|
||||
rtnl_link_put(orig_link);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pastaProcess(nsj_t* nsj, int pid, int err_pipe) {
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) {
|
||||
@@ -431,6 +439,7 @@ bool initParent(nsj_t* nsj, pid_t pid, int pipefd) {
|
||||
if (!nsj->njc.clone_newnet()) {
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_LIBNL3
|
||||
struct nl_sock* sk = nl_socket_alloc();
|
||||
if (!sk) {
|
||||
LOG_E("Could not allocate socket with nl_socket_alloc()");
|
||||
@@ -467,6 +476,14 @@ bool initParent(nsj_t* nsj, pid_t pid, int pipefd) {
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
if (!nsj->njc.iface_own().empty() || !nsj->njc.macvlan_iface().empty()) {
|
||||
LOG_E("Features requiring Netlink (iface_own, macvlan) are requested but nsjail "
|
||||
"was built without libnl3 support");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool isSocket(int fd) {
|
||||
@@ -768,6 +785,7 @@ static bool parseIp6(const std::string& ip_str, struct in6_addr* addr, int* mask
|
||||
return inet_pton(AF_INET6, ip.c_str(), addr) == 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNL3
|
||||
static bool applyTrafficRule(
|
||||
struct nl_sock* sk, const nsjail::NsJailConfig_TrafficRule& rule, int family) {
|
||||
struct rtnl_rule* rtnl_rule = rtnl_rule_alloc();
|
||||
@@ -855,6 +873,7 @@ static bool applyTrafficRule(
|
||||
rtnl_rule_put(rtnl_rule);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool initNsFromChild(nsj_t* nsj) {
|
||||
if (!nsj->njc.clone_newnet()) {
|
||||
@@ -869,6 +888,7 @@ bool initNsFromChild(nsj_t* nsj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNL3
|
||||
if (nsj->njc.traffic_rule_size() > 0) {
|
||||
struct nl_sock* sk = nl_socket_alloc();
|
||||
if (!sk) {
|
||||
@@ -891,6 +911,12 @@ bool initNsFromChild(nsj_t* nsj) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (nsj->njc.traffic_rule_size() > 0) {
|
||||
LOG_E("Traffic rules requested but nsjail was built without libnl3 support");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
114
nstun/nstun.cc
114
nstun/nstun.cc
@@ -6,8 +6,6 @@
|
||||
#include <linux/if_tun.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netlink/addr.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -18,6 +16,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <charconv>
|
||||
#include <thread>
|
||||
|
||||
#include "core.h"
|
||||
@@ -203,12 +202,8 @@ bool nstun_init_parent(int sock, nsj_t* nsj) {
|
||||
ctx->nsj = nsj;
|
||||
|
||||
auto assign_ip = [](const std::string& str, uint32_t* ip) {
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(str.c_str(), AF_INET, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == 4) {
|
||||
memcpy(ip, nl_addr_get_binary_addr(addr), 4);
|
||||
}
|
||||
nl_addr_put(addr);
|
||||
if (inet_pton(AF_INET, str.c_str(), ip) != 1) {
|
||||
LOG_E("Failed to parse IP: %s", str.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,41 +232,53 @@ bool nstun_init_parent(int sock, nsj_t* nsj) {
|
||||
}
|
||||
|
||||
auto parse_ip = [](const std::string& str, uint32_t* ip, uint32_t* mask) {
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(str.c_str(), AF_INET, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == 4) {
|
||||
memcpy(ip, nl_addr_get_binary_addr(addr), 4);
|
||||
std::string ip_str = str;
|
||||
int bits = 32;
|
||||
size_t pos = str.find('/');
|
||||
if (pos != std::string::npos) {
|
||||
ip_str = str.substr(0, pos);
|
||||
const char* p = str.c_str() + pos + 1;
|
||||
auto [ptr, ec] = std::from_chars(p, str.c_str() + str.length(), bits);
|
||||
if (ec != std::errc()) {
|
||||
LOG_E("Failed to parse mask bits: %s", p);
|
||||
return;
|
||||
}
|
||||
int bits = nl_addr_get_prefixlen(addr);
|
||||
*mask = (bits == 0) ? 0 : htonl(~((1ULL << (32 - bits)) - 1));
|
||||
nl_addr_put(addr);
|
||||
} else {
|
||||
LOG_E("Failed to parse IP/CIDR string: %s", str.c_str());
|
||||
}
|
||||
if (inet_pton(AF_INET, ip_str.c_str(), ip) != 1) {
|
||||
LOG_E("Failed to parse IP string: %s", ip_str.c_str());
|
||||
return;
|
||||
}
|
||||
*mask = (bits == 0) ? 0 : htonl(~((1ULL << (32 - bits)) - 1));
|
||||
};
|
||||
|
||||
auto parse_ip6 = [](const std::string& str, uint8_t* ip6, uint8_t* mask6) {
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(str.c_str(), AF_INET6, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == nstun::IPV6_ADDR_LEN) {
|
||||
memcpy(ip6, nl_addr_get_binary_addr(addr), nstun::IPV6_ADDR_LEN);
|
||||
std::string ip_str = str;
|
||||
int bits = 128;
|
||||
size_t pos = str.find('/');
|
||||
if (pos != std::string::npos) {
|
||||
ip_str = str.substr(0, pos);
|
||||
const char* p = str.c_str() + pos + 1;
|
||||
auto [ptr, ec] = std::from_chars(p, str.c_str() + str.length(), bits);
|
||||
if (ec != std::errc()) {
|
||||
LOG_E("Failed to parse mask bits: %s", p);
|
||||
return;
|
||||
}
|
||||
int bits = nl_addr_get_prefixlen(addr);
|
||||
memset(mask6, 0, nstun::IPV6_ADDR_LEN);
|
||||
for (int i = 0; i < (int)nstun::IPV6_ADDR_LEN; i++) {
|
||||
if (bits >= 8) {
|
||||
mask6[i] = 0xFF;
|
||||
bits -= 8;
|
||||
} else if (bits > 0) {
|
||||
mask6[i] = (uint8_t)(0xFF << (8 - bits));
|
||||
bits = 0;
|
||||
} else {
|
||||
mask6[i] = 0;
|
||||
}
|
||||
}
|
||||
if (inet_pton(AF_INET6, ip_str.c_str(), ip6) != 1) {
|
||||
LOG_E("Failed to parse IPv6 string: %s", ip_str.c_str());
|
||||
return;
|
||||
}
|
||||
memset(mask6, 0, nstun::IPV6_ADDR_LEN);
|
||||
for (int i = 0; i < (int)nstun::IPV6_ADDR_LEN; i++) {
|
||||
if (bits >= 8) {
|
||||
mask6[i] = 0xFF;
|
||||
bits -= 8;
|
||||
} else if (bits > 0) {
|
||||
mask6[i] = (uint8_t)(0xFF << (8 - bits));
|
||||
bits = 0;
|
||||
} else {
|
||||
mask6[i] = 0;
|
||||
}
|
||||
nl_addr_put(addr);
|
||||
} else {
|
||||
LOG_E("Failed to parse IPv6/CIDR string: %s", str.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -306,15 +313,8 @@ bool nstun_init_parent(int sock, nsj_t* nsj) {
|
||||
parse_ip(r.dst_ip(), &nr.dst_ip4, &nr.dst_mask4);
|
||||
}
|
||||
|
||||
if (r.has_redirect_ip()) {
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(r.redirect_ip().c_str(), AF_INET, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == 4) {
|
||||
memcpy(&nr.redirect_ip4, nl_addr_get_binary_addr(addr),
|
||||
sizeof(nr.redirect_ip4));
|
||||
}
|
||||
nl_addr_put(addr);
|
||||
}
|
||||
if (inet_pton(AF_INET, r.redirect_ip().c_str(), &nr.redirect_ip4) != 1) {
|
||||
LOG_E("Failed to parse redirect IP: %s", r.redirect_ip().c_str());
|
||||
}
|
||||
nr.redirect_port = r.has_redirect_port() ? r.redirect_port() : 0;
|
||||
|
||||
@@ -406,25 +406,17 @@ bool nstun_init_parent(int sock, nsj_t* nsj) {
|
||||
if (nr.action == NSTUN_ACTION_ENCAP_SOCKS5 ||
|
||||
nr.action == NSTUN_ACTION_ENCAP_CONNECT) {
|
||||
/* Proxy is always IPv4 */
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(r.redirect_ip().c_str(), AF_INET, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == 4) {
|
||||
memcpy(&nr.redirect_ip4,
|
||||
nl_addr_get_binary_addr(addr),
|
||||
sizeof(nr.redirect_ip4));
|
||||
}
|
||||
nl_addr_put(addr);
|
||||
if (inet_pton(AF_INET, r.redirect_ip().c_str(), &nr.redirect_ip4) !=
|
||||
1) {
|
||||
LOG_E("Failed to parse redirect IP: %s",
|
||||
r.redirect_ip().c_str());
|
||||
}
|
||||
} else {
|
||||
/* REDIRECT: target is IPv6 */
|
||||
struct nl_addr* addr;
|
||||
if (nl_addr_parse(r.redirect_ip().c_str(), AF_INET6, &addr) == 0) {
|
||||
if (nl_addr_get_len(addr) == 16) {
|
||||
memcpy(nr.redirect_ip6,
|
||||
nl_addr_get_binary_addr(addr),
|
||||
sizeof(nr.redirect_ip6));
|
||||
}
|
||||
nl_addr_put(addr);
|
||||
if (inet_pton(AF_INET6, r.redirect_ip().c_str(), nr.redirect_ip6) !=
|
||||
1) {
|
||||
LOG_E("Failed to parse redirect IPv6: %s",
|
||||
r.redirect_ip().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,6 @@ mount {
|
||||
}
|
||||
|
||||
exec_bin {
|
||||
path: "/bin/sh"
|
||||
path: "/bin/bash"
|
||||
arg: "-i"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user