From 84ba3607bf4b87e2f872e960c957d7d860acd83d Mon Sep 17 00:00:00 2001 From: flu0r1ne Date: Fri, 25 Aug 2023 19:05:30 -0500 Subject: Rename project wg2sd -> wg2nd, new CLI + generate 1. Renamed the project from wg2sd to wg2nd 2. Modified the _gen_netdev_cfg() function to handle the MTUBytes field. 3. Add new CLI with `generate` and `install` commands 4. Modified the gen_systemd_config() function to accept keyfile_or_output_path and filename parameters. - user can choose the name of the keyfile on the CLI - user can choose alternative output filename (instead of just using the interface name) --- test/wg2nd_test.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/wg2sd_test.cpp | 219 ---------------------------------------------------- 2 files changed, 219 insertions(+), 219 deletions(-) create mode 100644 test/wg2nd_test.cpp delete mode 100644 test/wg2sd_test.cpp (limited to 'test') diff --git a/test/wg2nd_test.cpp b/test/wg2nd_test.cpp new file mode 100644 index 0000000..39b0766 --- /dev/null +++ b/test/wg2nd_test.cpp @@ -0,0 +1,219 @@ +#include "utest.h" + +#include "wg2nd.hpp" +#include +#include + +namespace wg2nd { + extern bool _is_default_route(std::string const & cidr); + extern bool _is_ipv4_route(std::string const & cidr); +}; + +using namespace wg2nd; + +UTEST(wg2nd, ip_helpers) { + + std::array default_routes = { + "0/0", + "0.0/0", + "0.0.0/0", + "0.0.0.0/0", + "::/0", + "::0/0", + "::0/0", + "0000:0000:0000:0000::/0", + }; + + for(std::string const & s : default_routes) { + ASSERT_TRUE(_is_default_route(s)); + } + + std::array non_default_routes = { + "192.168.0.1/24", + "0.0.0.1/0", + "0.0.0.0/32", + "1/1", + "2001:db8::1/64", + "fe80::1/128", + "::1/128", + "2001:0db8:0000:0000::/64", + }; + + for(std::string const & s : non_default_routes) { + ASSERT_FALSE(_is_default_route(s)); + } + + std::array ipv4_route = { + "192.168.1.1", + "0.0.0.0/0", + "255.255.255.255/32", + "1.2.3.4/0" + }; + + for(std::string const & s : ipv4_route) { + ASSERT_TRUE(_is_ipv4_route(s)); + } + + std::array ipv6_route = { + "2001:db8::1/64", + "fe80::1/128", + "::1/128", + "2001:0db8:0000:0000::/64", + }; + + for(std::string const & s : ipv6_route) { + ASSERT_FALSE(_is_ipv4_route(s)); + } +} + +// Typical configuration, similar to that provided by mullvad.net +char const * CONFIG1 = ( + "[Interface]\n" + " # Device: Fast Mink\n" + " PrivateKey = APmSX97Yww7WyHrQGG3u7oUJAKRazSyXVu9lD+A3aW8=\n" + "Address = 10.14.123.142/32,fc00:aaaa:aaaa:aa01::6:ad78/128\n" + "DNS =10.0.0.2\n" + "[Peer]\n" + "PublicKey = kMIIVxitU3/1AnAGwdL5KazDQ97MnkuEVz2sWihALnQ= \n" + "AllowedIPs = 0.0.0.0/0,::0/0 # comment\n" + "Endpoint = 194.36.25.33:51820\n" +); + +// Configuration with multiple peers, interface peer tables are reversed +const char * CONFIG2 = ( + "[Peer]\n" + "PublicKey = sMYYPASxJslAuszh5PgUPysrzZHHBOzawJ8PFbRQrHI=\n" + "AllowedIPs = 192.168.1.2/32\n" + "Endpoint = 203.0.113.1:51820\n" + "\n" + "[Peer]\n" + "PublicKey = kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs=\n" + "AllowedIPs = 192.168.1.3/32\n" + "Endpoint = 203.0.113.2:51820\n" + "\n" + "[Interface]\n" + "PrivateKey = ED3TF8deMhmXHa7Jrp024uv5T7jKl7611vFV3C1P+EY=\n" + "Address = 192.168.1.1/24\n" +); + +// Configuration with persistant keepalive, psk, and multiple DNS entries +const char * CONFIG3 = ( + "[Interface]\n" + "PrivateKey = cJgeEfHUay0aKpV+k1lFK9nq9JJcqzKm8+Wh3EGtg1c=\n" + " Table=5\n" + "\t\tAddress = 192.168.1.1/24\n" + "DNS = 8.8.8.8,\t 8.8.4.4\n" + "ListenPort = 4444\n" + "Table = 42\n" + "\n" + "[Peer]\n" + " PublicKey = kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs=\n" + " AllowedIPs = 192.168.1.2/32\n" + "Endpoint = 203.0.113.1:51820\n" + "PersistentKeepalive = 25\n" + " PresharedKey = KIst3pK+YVHmM5k7NbNULKd2px9vaRsFi/y4E7NDWDQ=\n" +); + +const char * INVALID_CONFIG = ( + "PrivateKey = kPvfTBQxgHpaXI9wVj6JrtYKIJLVXrf0zg6ON7qUxl8=\n" + "Address = 192.168.1.1/24\n" + "[Interface]\n" +); + + +UTEST(wg2nd, parses_config) { + + // CONFIG1 + std::istringstream ss { CONFIG1 }; + + Config cfg = parse_config("wg", ss); + + ASSERT_STREQ(cfg.intf.name.c_str(), "wg"); + ASSERT_STREQ(cfg.intf.private_key.c_str(), "APmSX97Yww7WyHrQGG3u7oUJAKRazSyXVu9lD+A3aW8="); + ASSERT_EQ(cfg.intf.table, 0ul); + ASSERT_FALSE(cfg.intf.listen_port.has_value()); + ASSERT_EQ(cfg.intf.DNS.size(), 1ull); + ASSERT_STREQ(cfg.intf.DNS.back().c_str(), "10.0.0.2"); + ASSERT_EQ(cfg.peers.size(), 1ull); + + const Peer & peer = cfg.peers[0]; + + ASSERT_STREQ(peer.endpoint.c_str(), "194.36.25.33:51820"); + ASSERT_STREQ(peer.allowed_ips[0].route.c_str(), "0.0.0.0/0"); + ASSERT_TRUE(peer.allowed_ips[0].is_ipv4); + ASSERT_TRUE(peer.allowed_ips[0].is_default_route); + ASSERT_STREQ(peer.allowed_ips[1].route.c_str(), "::0/0"); + ASSERT_FALSE(peer.allowed_ips[1].is_ipv4); + ASSERT_TRUE(peer.allowed_ips[1].is_default_route); + + ASSERT_STREQ(peer.public_key.c_str(), "kMIIVxitU3/1AnAGwdL5KazDQ97MnkuEVz2sWihALnQ="); + ASSERT_STREQ(peer.preshared_key.c_str(), ""); + ASSERT_STREQ(peer.persistent_keepalive.c_str(), ""); + + // CONFIG2 + std::istringstream ss2 { CONFIG2 }; + + Config cfg2 = parse_config("wg", ss2); + + ASSERT_STREQ(cfg2.intf.name.c_str(), "wg"); + ASSERT_FALSE(cfg2.intf.listen_port.has_value()); + ASSERT_STREQ(cfg2.intf.private_key.c_str(), "ED3TF8deMhmXHa7Jrp024uv5T7jKl7611vFV3C1P+EY="); + ASSERT_EQ(cfg2.intf.table, 0ul); + ASSERT_EQ(cfg2.intf.DNS.size(), 0ull); + + ASSERT_EQ(cfg2.peers.size(), 2ull); + + const Peer &peer2_1 = cfg2.peers[0]; + + ASSERT_STREQ(peer2_1.endpoint.c_str(), "203.0.113.1:51820"); + ASSERT_STREQ(peer2_1.allowed_ips[0].route.c_str(), "192.168.1.2/32"); + ASSERT_TRUE(peer2_1.allowed_ips[0].is_ipv4); + ASSERT_FALSE(peer2_1.allowed_ips[0].is_default_route); + ASSERT_STREQ(peer2_1.public_key.c_str(), "sMYYPASxJslAuszh5PgUPysrzZHHBOzawJ8PFbRQrHI="); + ASSERT_STREQ(peer2_1.preshared_key.c_str(), ""); + ASSERT_STREQ(peer2_1.persistent_keepalive.c_str(), ""); + + const Peer &peer2_2 = cfg2.peers[1]; + + ASSERT_STREQ(peer2_2.endpoint.c_str(), "203.0.113.2:51820"); + ASSERT_STREQ(peer2_2.allowed_ips[0].route.c_str(), "192.168.1.3/32"); + ASSERT_TRUE(peer2_2.allowed_ips[0].is_ipv4); + ASSERT_FALSE(peer2_2.allowed_ips[0].is_default_route); + ASSERT_STREQ(peer2_2.public_key.c_str(), "kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs="); + ASSERT_STREQ(peer2_2.preshared_key.c_str(), ""); + ASSERT_STREQ(peer2_2.persistent_keepalive.c_str(), ""); + + // CONFIG3 + std::istringstream ss3 { CONFIG3 }; + + Config cfg3 = parse_config("wg", ss3); + + ASSERT_STREQ(cfg3.intf.name.c_str(), "wg"); + ASSERT_STREQ(cfg3.intf.private_key.c_str(), "cJgeEfHUay0aKpV+k1lFK9nq9JJcqzKm8+Wh3EGtg1c="); + ASSERT_EQ(cfg3.intf.table, 42ul); + uint16_t port = cfg3.intf.listen_port.value(); + ASSERT_EQ(port, 4444); + ASSERT_EQ(cfg3.intf.DNS.size(), 2ull); + ASSERT_STREQ(cfg3.intf.DNS[0].c_str(), "8.8.8.8"); + ASSERT_STREQ(cfg3.intf.DNS[1].c_str(), "8.8.4.4"); + + ASSERT_EQ(cfg3.peers.size(), 1ull); + + const Peer &peer3 = cfg3.peers[0]; + + ASSERT_STREQ(peer3.endpoint.c_str(), "203.0.113.1:51820"); + ASSERT_STREQ(peer3.allowed_ips[0].route.c_str(), "192.168.1.2/32"); + ASSERT_TRUE(peer3.allowed_ips[0].is_ipv4); + ASSERT_FALSE(peer3.allowed_ips[0].is_default_route); + ASSERT_STREQ(peer3.public_key.c_str(), "kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs="); + ASSERT_STREQ(peer3.preshared_key.c_str(), "KIst3pK+YVHmM5k7NbNULKd2px9vaRsFi/y4E7NDWDQ="); + ASSERT_STREQ(peer3.persistent_keepalive.c_str(), "25"); + + + // INVALID_CONFIG + std::istringstream ss4 { INVALID_CONFIG }; + + ASSERT_EXCEPTION(parse_config("wg", ss4), ParsingException); +} + +UTEST_MAIN() diff --git a/test/wg2sd_test.cpp b/test/wg2sd_test.cpp deleted file mode 100644 index 5d57ac9..0000000 --- a/test/wg2sd_test.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include "utest.h" - -#include "wg2sd.hpp" -#include -#include - -namespace wg2sd { - extern bool _is_default_route(std::string const & cidr); - extern bool _is_ipv4_route(std::string const & cidr); -}; - -using namespace wg2sd; - -UTEST(wg2sd, ip_helpers) { - - std::array default_routes = { - "0/0", - "0.0/0", - "0.0.0/0", - "0.0.0.0/0", - "::/0", - "::0/0", - "::0/0", - "0000:0000:0000:0000::/0", - }; - - for(std::string const & s : default_routes) { - ASSERT_TRUE(_is_default_route(s)); - } - - std::array non_default_routes = { - "192.168.0.1/24", - "0.0.0.1/0", - "0.0.0.0/32", - "1/1", - "2001:db8::1/64", - "fe80::1/128", - "::1/128", - "2001:0db8:0000:0000::/64", - }; - - for(std::string const & s : non_default_routes) { - ASSERT_FALSE(_is_default_route(s)); - } - - std::array ipv4_route = { - "192.168.1.1", - "0.0.0.0/0", - "255.255.255.255/32", - "1.2.3.4/0" - }; - - for(std::string const & s : ipv4_route) { - ASSERT_TRUE(_is_ipv4_route(s)); - } - - std::array ipv6_route = { - "2001:db8::1/64", - "fe80::1/128", - "::1/128", - "2001:0db8:0000:0000::/64", - }; - - for(std::string const & s : ipv6_route) { - ASSERT_FALSE(_is_ipv4_route(s)); - } -} - -// Typical configuration, similar to that provided by mullvad.net -char const * CONFIG1 = ( - "[Interface]\n" - " # Device: Fast Mink\n" - " PrivateKey = APmSX97Yww7WyHrQGG3u7oUJAKRazSyXVu9lD+A3aW8=\n" - "Address = 10.14.123.142/32,fc00:aaaa:aaaa:aa01::6:ad78/128\n" - "DNS =10.0.0.2\n" - "[Peer]\n" - "PublicKey = kMIIVxitU3/1AnAGwdL5KazDQ97MnkuEVz2sWihALnQ= \n" - "AllowedIPs = 0.0.0.0/0,::0/0 # comment\n" - "Endpoint = 194.36.25.33:51820\n" -); - -// Configuration with multiple peers, interface peer tables are reversed -const char * CONFIG2 = ( - "[Peer]\n" - "PublicKey = sMYYPASxJslAuszh5PgUPysrzZHHBOzawJ8PFbRQrHI=\n" - "AllowedIPs = 192.168.1.2/32\n" - "Endpoint = 203.0.113.1:51820\n" - "\n" - "[Peer]\n" - "PublicKey = kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs=\n" - "AllowedIPs = 192.168.1.3/32\n" - "Endpoint = 203.0.113.2:51820\n" - "\n" - "[Interface]\n" - "PrivateKey = ED3TF8deMhmXHa7Jrp024uv5T7jKl7611vFV3C1P+EY=\n" - "Address = 192.168.1.1/24\n" -); - -// Configuration with persistant keepalive, psk, and multiple DNS entries -const char * CONFIG3 = ( - "[Interface]\n" - "PrivateKey = cJgeEfHUay0aKpV+k1lFK9nq9JJcqzKm8+Wh3EGtg1c=\n" - " Table=5\n" - "\t\tAddress = 192.168.1.1/24\n" - "DNS = 8.8.8.8,\t 8.8.4.4\n" - "ListenPort = 4444\n" - "Table = 42\n" - "\n" - "[Peer]\n" - " PublicKey = kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs=\n" - " AllowedIPs = 192.168.1.2/32\n" - "Endpoint = 203.0.113.1:51820\n" - "PersistentKeepalive = 25\n" - " PresharedKey = KIst3pK+YVHmM5k7NbNULKd2px9vaRsFi/y4E7NDWDQ=\n" -); - -const char * INVALID_CONFIG = ( - "PrivateKey = kPvfTBQxgHpaXI9wVj6JrtYKIJLVXrf0zg6ON7qUxl8=\n" - "Address = 192.168.1.1/24\n" - "[Interface]\n" -); - - -UTEST(wg2sd, parses_config) { - - // CONFIG1 - std::istringstream ss { CONFIG1 }; - - Config cfg = parse_config("wg", ss); - - ASSERT_STREQ(cfg.intf.name.c_str(), "wg"); - ASSERT_STREQ(cfg.intf.private_key.c_str(), "APmSX97Yww7WyHrQGG3u7oUJAKRazSyXVu9lD+A3aW8="); - ASSERT_EQ(cfg.intf.table, 0ul); - ASSERT_FALSE(cfg.intf.listen_port.has_value()); - ASSERT_EQ(cfg.intf.DNS.size(), 1ull); - ASSERT_STREQ(cfg.intf.DNS.back().c_str(), "10.0.0.2"); - ASSERT_EQ(cfg.peers.size(), 1ull); - - const Peer & peer = cfg.peers[0]; - - ASSERT_STREQ(peer.endpoint.c_str(), "194.36.25.33:51820"); - ASSERT_STREQ(peer.allowed_ips[0].route.c_str(), "0.0.0.0/0"); - ASSERT_TRUE(peer.allowed_ips[0].is_ipv4); - ASSERT_TRUE(peer.allowed_ips[0].is_default_route); - ASSERT_STREQ(peer.allowed_ips[1].route.c_str(), "::0/0"); - ASSERT_FALSE(peer.allowed_ips[1].is_ipv4); - ASSERT_TRUE(peer.allowed_ips[1].is_default_route); - - ASSERT_STREQ(peer.public_key.c_str(), "kMIIVxitU3/1AnAGwdL5KazDQ97MnkuEVz2sWihALnQ="); - ASSERT_STREQ(peer.preshared_key.c_str(), ""); - ASSERT_STREQ(peer.persistent_keepalive.c_str(), ""); - - // CONFIG2 - std::istringstream ss2 { CONFIG2 }; - - Config cfg2 = parse_config("wg", ss2); - - ASSERT_STREQ(cfg2.intf.name.c_str(), "wg"); - ASSERT_FALSE(cfg2.intf.listen_port.has_value()); - ASSERT_STREQ(cfg2.intf.private_key.c_str(), "ED3TF8deMhmXHa7Jrp024uv5T7jKl7611vFV3C1P+EY="); - ASSERT_EQ(cfg2.intf.table, 0ul); - ASSERT_EQ(cfg2.intf.DNS.size(), 0ull); - - ASSERT_EQ(cfg2.peers.size(), 2ull); - - const Peer &peer2_1 = cfg2.peers[0]; - - ASSERT_STREQ(peer2_1.endpoint.c_str(), "203.0.113.1:51820"); - ASSERT_STREQ(peer2_1.allowed_ips[0].route.c_str(), "192.168.1.2/32"); - ASSERT_TRUE(peer2_1.allowed_ips[0].is_ipv4); - ASSERT_FALSE(peer2_1.allowed_ips[0].is_default_route); - ASSERT_STREQ(peer2_1.public_key.c_str(), "sMYYPASxJslAuszh5PgUPysrzZHHBOzawJ8PFbRQrHI="); - ASSERT_STREQ(peer2_1.preshared_key.c_str(), ""); - ASSERT_STREQ(peer2_1.persistent_keepalive.c_str(), ""); - - const Peer &peer2_2 = cfg2.peers[1]; - - ASSERT_STREQ(peer2_2.endpoint.c_str(), "203.0.113.2:51820"); - ASSERT_STREQ(peer2_2.allowed_ips[0].route.c_str(), "192.168.1.3/32"); - ASSERT_TRUE(peer2_2.allowed_ips[0].is_ipv4); - ASSERT_FALSE(peer2_2.allowed_ips[0].is_default_route); - ASSERT_STREQ(peer2_2.public_key.c_str(), "kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs="); - ASSERT_STREQ(peer2_2.preshared_key.c_str(), ""); - ASSERT_STREQ(peer2_2.persistent_keepalive.c_str(), ""); - - // CONFIG3 - std::istringstream ss3 { CONFIG3 }; - - Config cfg3 = parse_config("wg", ss3); - - ASSERT_STREQ(cfg3.intf.name.c_str(), "wg"); - ASSERT_STREQ(cfg3.intf.private_key.c_str(), "cJgeEfHUay0aKpV+k1lFK9nq9JJcqzKm8+Wh3EGtg1c="); - ASSERT_EQ(cfg3.intf.table, 42ul); - uint16_t port = cfg3.intf.listen_port.value(); - ASSERT_EQ(port, 4444); - ASSERT_EQ(cfg3.intf.DNS.size(), 2ull); - ASSERT_STREQ(cfg3.intf.DNS[0].c_str(), "8.8.8.8"); - ASSERT_STREQ(cfg3.intf.DNS[1].c_str(), "8.8.4.4"); - - ASSERT_EQ(cfg3.peers.size(), 1ull); - - const Peer &peer3 = cfg3.peers[0]; - - ASSERT_STREQ(peer3.endpoint.c_str(), "203.0.113.1:51820"); - ASSERT_STREQ(peer3.allowed_ips[0].route.c_str(), "192.168.1.2/32"); - ASSERT_TRUE(peer3.allowed_ips[0].is_ipv4); - ASSERT_FALSE(peer3.allowed_ips[0].is_default_route); - ASSERT_STREQ(peer3.public_key.c_str(), "kB9CSPsPS5irR0ZpVAHZKPNHLQKjIFjmgc6MSCAiWUs="); - ASSERT_STREQ(peer3.preshared_key.c_str(), "KIst3pK+YVHmM5k7NbNULKd2px9vaRsFi/y4E7NDWDQ="); - ASSERT_STREQ(peer3.persistent_keepalive.c_str(), "25"); - - - // INVALID_CONFIG - std::istringstream ss4 { INVALID_CONFIG }; - - ASSERT_EXCEPTION(parse_config("wg", ss4), ParsingException); -} - -UTEST_MAIN() -- cgit v1.2.3