github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/supervisor/daemon/wireguard/wginterface/firewall/blocker.go (about) 1 //go:build windows 2 3 /* SPDX-License-Identifier: MIT 4 * 5 * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved. 6 */ 7 8 package firewall 9 10 import ( 11 "errors" 12 "net" 13 "unsafe" 14 15 "golang.org/x/sys/windows" 16 ) 17 18 type wfpObjectInstaller func(uintptr) error 19 20 // Fundamental WireGuard specific WFP objects. 21 type baseObjects struct { 22 provider windows.GUID 23 filters windows.GUID 24 } 25 26 var wfpSession uintptr 27 28 func createWfpSession() (uintptr, error) { 29 sessionDisplayData, err := createWtFwpmDisplayData0("WireGuard", "WireGuard dynamic session") 30 if err != nil { 31 return 0, wrapErr(err) 32 } 33 34 session := wtFwpmSession0{ 35 displayData: *sessionDisplayData, 36 flags: cFWPM_SESSION_FLAG_DYNAMIC, 37 txnWaitTimeoutInMSec: windows.INFINITE, 38 } 39 40 sessionHandle := uintptr(0) 41 42 err = fwpmEngineOpen0(nil, cRPC_C_AUTHN_WINNT, nil, &session, unsafe.Pointer(&sessionHandle)) 43 if err != nil { 44 return 0, wrapErr(err) 45 } 46 47 return sessionHandle, nil 48 } 49 50 func registerBaseObjects(session uintptr) (*baseObjects, error) { 51 bo := &baseObjects{} 52 var err error 53 bo.provider, err = windows.GenerateGUID() 54 if err != nil { 55 return nil, wrapErr(err) 56 } 57 bo.filters, err = windows.GenerateGUID() 58 if err != nil { 59 return nil, wrapErr(err) 60 } 61 62 // 63 // Register provider. 64 // 65 { 66 displayData, err := createWtFwpmDisplayData0("WireGuard", "WireGuard provider") 67 if err != nil { 68 return nil, wrapErr(err) 69 } 70 provider := wtFwpmProvider0{ 71 providerKey: bo.provider, 72 displayData: *displayData, 73 } 74 err = fwpmProviderAdd0(session, &provider, 0) 75 if err != nil { 76 // TODO: cleanup entire call chain of these if failure? 77 return nil, wrapErr(err) 78 } 79 } 80 81 // 82 // Register filters sublayer. 83 // 84 { 85 displayData, err := createWtFwpmDisplayData0("WireGuard filters", "Permissive and blocking filters") 86 if err != nil { 87 return nil, wrapErr(err) 88 } 89 sublayer := wtFwpmSublayer0{ 90 subLayerKey: bo.filters, 91 displayData: *displayData, 92 providerKey: &bo.provider, 93 weight: ^uint16(0), 94 } 95 err = fwpmSubLayerAdd0(session, &sublayer, 0) 96 if err != nil { 97 return nil, wrapErr(err) 98 } 99 } 100 101 return bo, nil 102 } 103 104 // EnableFirewall enable firewall 105 func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []net.IP) error { 106 if wfpSession != 0 { 107 return errors.New("The firewall has already been enabled") 108 } 109 110 session, err := createWfpSession() 111 if err != nil { 112 return wrapErr(err) 113 } 114 115 objectInstaller := func(session uintptr) error { 116 baseObjects, err := registerBaseObjects(session) 117 if err != nil { 118 return wrapErr(err) 119 } 120 121 err = permitSupervisorWireGuardService(session, baseObjects, 15) 122 if err != nil { 123 return wrapErr(err) 124 } 125 126 err = permitMystWireGuardService(session, baseObjects, 15) 127 if err != nil { 128 return wrapErr(err) 129 } 130 131 if !doNotRestrict { 132 if len(restrictToDNSServers) > 0 { 133 err = blockDNS(restrictToDNSServers, session, baseObjects, 15, 14) 134 if err != nil { 135 return wrapErr(err) 136 } 137 } 138 139 err = permitLoopback(session, baseObjects, 13) 140 if err != nil { 141 return wrapErr(err) 142 } 143 144 err = permitTunInterface(session, baseObjects, 12, luid) 145 if err != nil { 146 return wrapErr(err) 147 } 148 149 err = permitDHCPIPv4(session, baseObjects, 12) 150 if err != nil { 151 return wrapErr(err) 152 } 153 154 err = permitDHCPIPv6(session, baseObjects, 12) 155 if err != nil { 156 return wrapErr(err) 157 } 158 159 err = permitNdp(session, baseObjects, 12) 160 if err != nil { 161 return wrapErr(err) 162 } 163 164 /* TODO: actually evaluate if this does anything and if we need this. It's layer 2; our other rules are layer 3. 165 * In other words, if somebody complains, try enabling it. For now, keep it off. 166 err = permitHyperV(session, baseObjects, 12) 167 if err != nil { 168 return wrapErr(err) 169 } 170 */ 171 172 err = blockAll(session, baseObjects, 0) 173 if err != nil { 174 return wrapErr(err) 175 } 176 } 177 178 return nil 179 } 180 181 err = runTransaction(session, objectInstaller) 182 if err != nil { 183 fwpmEngineClose0(session) 184 return wrapErr(err) 185 } 186 187 wfpSession = session 188 return nil 189 } 190 191 // DisableFirewall disable firewall 192 func DisableFirewall() { 193 if wfpSession != 0 { 194 fwpmEngineClose0(wfpSession) 195 wfpSession = 0 196 } 197 }