From 4959d8079bec7f9cf3dcad8224bf0b4db955bd1b Mon Sep 17 00:00:00 2001 From: travis laduke Date: Mon, 19 Dec 2022 13:26:29 -0800 Subject: [PATCH] enable ICMP in windows firewall --- osdep/WinFWHelper.cpp | 172 ++++++++++++++++++ osdep/WinFWHelper.hpp | 31 ++++ service/OneService.cpp | 19 +- windows/ZeroTierOne/ZeroTierOne.vcxproj | 2 + .../ZeroTierOne/ZeroTierOne.vcxproj.filters | 6 + 5 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 osdep/WinFWHelper.cpp create mode 100644 osdep/WinFWHelper.hpp diff --git a/osdep/WinFWHelper.cpp b/osdep/WinFWHelper.cpp new file mode 100644 index 000000000..40f38977e --- /dev/null +++ b/osdep/WinFWHelper.cpp @@ -0,0 +1,172 @@ +#include "WinFWHelper.hpp" + + +namespace ZeroTier { + + + +void ZeroTier::WinFWHelper::newICMPRule(const InetAddress& ip, uint64_t nwid) +{ + char nwString[32] = { 0 }; + char ipbuf[64]; + + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + ip.toString(ipbuf); + + if (ip.isV4()) { + WinFWHelper::newICMPv4Rule(ipbuf, nwid); + } + else { + WinFWHelper::newICMPv6Rule(ipbuf, nwid); + } +} + +void ZeroTier::WinFWHelper::removeICMPRule(const InetAddress& ip, uint64_t nwid) +{ + char nwString[32] = { 0 }; + char ipbuf[64]; + + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + ip.toString(ipbuf); + + if (ip.isV4()) { + WinFWHelper::removeICMPv4Rule(ipbuf, nwid); + } + else { + WinFWHelper::removeICMPv6Rule(ipbuf, nwid); + } +} + + +void WinFWHelper::newICMPv4Rule(std::string address, uint64_t nwid) +{ + // allows icmp, scoped to a specific ip address and interface name + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + address + + R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" + + " -Protocol ICMPv4 -Action Allow" + + " -LocalAddress " + address + "\"\r\n"; + + _run(cmd); +} + +void WinFWHelper::newICMPv6Rule(std::string address, uint64_t nwid) +{ + // allows icmp, scoped to a specific ip address and interface name + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + address + + R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" + + " -Protocol ICMPv6 -Action Allow" + + " -LocalAddress " + address + "\"\r\n"; + + _run(cmd); +} + +void WinFWHelper::removeICMPv4Rule(std::string addr, uint64_t nwid) +{ + // removes 1 icmp firewall rule + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + addr + + "\"\r\n"; + + _run(cmd); +} + +void WinFWHelper::removeICMPv6Rule(std::string addr, uint64_t nwid) +{ + // removes 1 icmp firewall rule + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + addr + + "\"\r\n"; + + _run(cmd); +} + +void WinFWHelper::removeICMPv4Rules(uint64_t nwid) +{ + // removes all icmp firewall rules for this network id + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + "*\" \r\n"; + + _run(cmd); +} + +void WinFWHelper::removeICMPv6Rules(uint64_t nwid) +{ + // removes all icmp firewall rules for this network id + + char nwString[32] = { 0 }; + sprintf(nwString, "%.16llx", nwid); + std::string nwString2 = { nwString }; + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + "*\" \r\n"; + + _run(cmd); +} + +void WinFWHelper::removeICMPRules() +{ + // removes all icmp firewall rules for all networks + + std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmp*)" + std::string("\r\n"); + + _run(cmd); +} + +void WinFWHelper::removeICMPRules(uint64_t nwid) +{ + // removes all icmp firewall rules for this network + WinFWHelper::removeICMPv4Rules(nwid); + WinFWHelper::removeICMPv6Rules(nwid); +} + + + +void WinFWHelper::_run(std::string cmd) +{ + + #ifdef ZT_DEBUG + fprintf(stderr, cmd.c_str()); + #endif + + STARTUPINFOA startupInfo; + PROCESS_INFORMATION processInfo; + startupInfo.cb = sizeof(startupInfo); + memset(&startupInfo, 0, sizeof(STARTUPINFOA)); + memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); + + if (CreateProcessA(NULL, (LPSTR)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); + + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + } +} + + + +} // namespace ZeroTier \ No newline at end of file diff --git a/osdep/WinFWHelper.hpp b/osdep/WinFWHelper.hpp new file mode 100644 index 000000000..a8d9e27aa --- /dev/null +++ b/osdep/WinFWHelper.hpp @@ -0,0 +1,31 @@ +#ifndef WIN_FW_HELPER_H_ +#define WIN_FW_HELPER_H_ + +#include "../node/InetAddress.hpp" + +#include +#include + +namespace ZeroTier { + +class WinFWHelper { + public: + static void newICMPRule(const InetAddress& ip, uint64_t nwid); + static void removeICMPRule(const InetAddress& ip, uint64_t nwid); + static void removeICMPRules(uint64_t nwid); + static void removeICMPRules(); + + + private: + static void _run(std::string cmd); + static void newICMPv4Rule(std::string address, uint64_t nwid); + static void newICMPv6Rule(std::string address, uint64_t nwid); + static void removeICMPv4Rule(std::string address, uint64_t nwid); + static void removeICMPv6Rule(std::string address, uint64_t nwid); + static void removeICMPv4Rules(uint64_t nwid); + static void removeICMPv6Rules(uint64_t nwid); +}; + +} // namespace ZeroTier + +#endif \ No newline at end of file diff --git a/service/OneService.cpp b/service/OneService.cpp index 5984b8b86..3dd344e0e 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -78,6 +78,7 @@ #include "../osdep/MacDNSHelper.hpp" #elif defined(__WINDOWS__) #include "../osdep/WinDNSHelper.hpp" +#include "../osdep/WinFWHelper.hpp" #endif #ifdef ZT_USE_SYSTEM_HTTP_PARSER @@ -847,6 +848,9 @@ public: virtual ~OneServiceImpl() { +#ifdef __WINDOWS__ + WinFWHelper::removeICMPRules(); +#endif _binder.closeAll(_phy); _phy.close(_localControlSocket4); _phy.close(_localControlSocket6); @@ -855,6 +859,8 @@ public: curl_global_cleanup(); #endif + + #ifdef ZT_USE_MINIUPNPC delete _portMapper; #endif @@ -899,6 +905,7 @@ public: _node = new Node(this,(void *)0,&cb,OSUtils::now()); } + // local.conf readLocalSettings(); applyLocalConfig(); @@ -2262,6 +2269,10 @@ public: if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { if (!n.tap()->removeIp(*ip)) fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); + + #ifdef __WINDOWS__ + WinFWHelper::removeICMPRule(*ip, n.config().nwid); + #endif } } @@ -2269,6 +2280,10 @@ public: if (std::find(n.managedIps().begin(),n.managedIps().end(),*ip) == n.managedIps().end()) { if (!n.tap()->addIp(*ip)) fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); + + #ifdef __WINDOWS__ + WinFWHelper::newICMPRule(*ip, n.config().nwid); + #endif } } @@ -2749,8 +2764,10 @@ public: n.tap().reset(); _nets.erase(nwid); #if defined(__WINDOWS__) && !defined(ZT_SDK) - if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY)&&(winInstanceId.length() > 0)) + if ((op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) && (winInstanceId.length() > 0)) { WindowsEthernetTap::deletePersistentTapDevice(winInstanceId.c_str()); + WinFWHelper::removeICMPRules(nwid); + } #endif if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) { char nlcpath[256]; diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 8b2712d3f..36e50ffac 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -124,6 +124,7 @@ + true true @@ -241,6 +242,7 @@ + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index ebdd33267..ecf664f82 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -288,6 +288,9 @@ Source Files\node + + Source Files\osdep + @@ -551,6 +554,9 @@ Header Files\osdep + + Header Files\osdep +