aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflu0r1ne <flu0r1ne@flu0r1ne.net>2023-08-18 01:13:07 -0500
committerflu0r1ne <flu0r1ne@flu0r1ne.net>2023-08-18 01:13:07 -0500
commit2f0a9c87bd5acd8fc0852f599599d031cde44bbe (patch)
treec4adb81a041d3cb7428c7c11c9cf8d88751b9160
parentd6e19ce0a112bd2403ad0cb274808ce3e749b459 (diff)
downloadwg2nd-2f0a9c87bd5acd8fc0852f599599d031cde44bbe.tar.xz
wg2nd-2f0a9c87bd5acd8fc0852f599599d031cde44bbe.zip
Add firewall rule generator
-rw-r--r--src/main.cpp17
-rw-r--r--src/wg2sd.cpp63
-rw-r--r--src/wg2sd.hpp1
3 files changed, 77 insertions, 4 deletions
diff --git a/src/main.cpp b/src/main.cpp
index b592aa9..19b5ced 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -89,10 +89,11 @@ void err(char const * format, ...) {
}
void print_help(char const * prog) {
- err("Usage: %s [ -o OUTPUT_PATH ] CONFIG_FILE", prog);
+ err("Usage: %s [ -h | -f | -o OUTPUT_PATH ] CONFIG_FILE", prog);
err("Options:");
err("-o OUTPUT_PATH\tSet the output path (default is /etc/systemd/network)");
- err("-h\t\tDisplay this help message");
+ err("-f \tOutput firewall rules");
+ err("-h \tDisplay this help message");
exit(EXIT_SUCCESS);
}
@@ -144,12 +145,16 @@ void write_systemd_file(SystemdFilespec const & filespec, std::string output_pat
int main(int argc, char ** argv) {
int opt;
std::filesystem::path output_path = "/etc/systemd/network";
+ bool print_firewall_rules = false;
- while ((opt = getopt(argc, argv, "o:h")) != -1) {
+ while ((opt = getopt(argc, argv, "o:fh")) != -1) {
switch (opt) {
case 'o':
output_path = optarg;
break;
+ case 'f':
+ print_firewall_rules = true;
+ break;
case 'h':
print_help(argv[0]);
break;
@@ -186,6 +191,12 @@ int main(int argc, char ** argv) {
}
+ if(print_firewall_rules) {
+ fprintf(stdout, "%s", cfg.firewall.c_str());
+
+ return 0;
+ }
+
if(!std::filesystem::path(output_path).is_absolute()) {
output_path = std::filesystem::absolute(output_path);
}
diff --git a/src/wg2sd.cpp b/src/wg2sd.cpp
index 2087cf5..4c39a03 100644
--- a/src/wg2sd.cpp
+++ b/src/wg2sd.cpp
@@ -6,6 +6,7 @@
#include <regex>
#include <argon2.h>
+#include <string_view>
std::string hashed_keyfile_name(std::string const & priv_key) {
constexpr uint8_t const SALT[] = {
@@ -70,6 +71,16 @@ namespace wg2sd {
return std::regex_match(cidr, ipv4);
}
+ std::string_view _get_addr(std::string_view const & cidr) {
+ size_t suffix = cidr.rfind('/');
+
+ if(suffix == std::string::npos) {
+ return cidr;
+ } else {
+ return cidr.substr(0, suffix);
+ }
+ }
+
constexpr uint32_t MAIN_TABLE = 254;
constexpr uint32_t LOCAL_TABLE = 255;
@@ -292,6 +303,55 @@ namespace wg2sd {
return cfg;
}
+ static void _write_table(std::stringstream & firewall, Config const & cfg, std::vector<std::string_view> addrs, bool ipv4) {
+ char const * ip = ipv4 ? "ip" : "ip6";
+
+ firewall << "table " << ip << " " << cfg.intf.name << " {\n"
+ << " chain preraw {\n"
+ << " type filter hook prerouting priority raw; policy accept;\n";
+
+ for(std::string_view const & addr : addrs) {
+ firewall << " iifname != \"" << cfg.intf.name << "\" " << ip << " daddr " << addr << " fib saddr type != local drop;\n";
+ }
+
+ firewall << " }\n"
+ << "\n"
+ << " chain premangle {\n"
+ << " type filter hook prerouting priority mangle; policy accept;\n"
+ << " meta l4proto udp meta mark set ct mark;\n"
+ << " }\n"
+ << "\n"
+ << " chain postmangle {\n"
+ << " type filter hook postrouting priority mangle; policy accept;\n"
+ << " meta l4proto udp meta mark " << std::hex << cfg.intf.table << std::dec << "ct mark set meta mark;\n"
+ << " }\n"
+ << "}\n";
+
+ }
+
+ std::string _gen_nftables_firewall(Config const & cfg) {
+ std::stringstream firewall;
+
+ std::vector<std::string_view> ipv4_addrs;
+ std::vector<std::string_view> ipv6_addrs;
+
+ for(std::string const & addr : cfg.intf.addresses) {
+ if(_is_ipv4_route(addr)) {
+ ipv4_addrs.push_back(_get_addr(addr));
+ } else {
+ ipv6_addrs.push_back(_get_addr(addr));
+ }
+ }
+
+ _write_table(firewall, cfg, ipv4_addrs, true);
+
+ firewall << "\n";
+
+ _write_table(firewall, cfg, ipv6_addrs, false);
+
+ return firewall.str();
+ }
+
static std::string _gen_netdev_cfg(Config const & cfg, uint32_t fwd_table, std::string const & private_keyfile,
std::vector<SystemdFilespec> & symmetric_keyfiles, std::string const & output_path) {
std::stringstream netdev;
@@ -526,7 +586,8 @@ if(!cfg.intf.field_.empty()) { \
.contents = cfg.intf.private_key + "\n",
},
.symmetric_keyfiles = std::move(symmetric_keyfiles),
- .warnings = std::move(warnings)
+ .warnings = std::move(warnings),
+ .firewall = _gen_nftables_firewall(cfg),
};
}
diff --git a/src/wg2sd.hpp b/src/wg2sd.hpp
index ea6f7fe..e80a284 100644
--- a/src/wg2sd.hpp
+++ b/src/wg2sd.hpp
@@ -127,6 +127,7 @@ namespace wg2sd {
std::vector<SystemdFilespec> symmetric_keyfiles;
std::vector<std::string> warnings;
+ std::string firewall;
};
std::string interface_name_from_filename(std::filesystem::path config_path);