github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/supervisor/daemon/wireguard/wginterface/firewall/rules.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 "encoding/binary" 12 "errors" 13 "net" 14 "runtime" 15 "unsafe" 16 17 "golang.org/x/sys/windows" 18 ) 19 20 // Known addresses. 21 var ( 22 linkLocal = wtFwpV6AddrAndMask{[16]uint8{0xfe, 0x80}, 10} 23 24 linkLocalDHCPMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2}} 25 siteLocalDHCPMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x3}} 26 27 linkLocalRouterMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}} 28 ) 29 30 func permitTunInterface(session uintptr, baseObjects *baseObjects, weight uint8, ifLUID uint64) error { 31 ifaceCondition := wtFwpmFilterCondition0{ 32 fieldKey: cFWPM_CONDITION_IP_LOCAL_INTERFACE, 33 matchType: cFWP_MATCH_EQUAL, 34 conditionValue: wtFwpConditionValue0{ 35 _type: cFWP_UINT64, 36 value: (uintptr)(unsafe.Pointer(&ifLUID)), 37 }, 38 } 39 40 filter := wtFwpmFilter0{ 41 providerKey: &baseObjects.provider, 42 subLayerKey: baseObjects.filters, 43 weight: filterWeight(weight), 44 numFilterConditions: 1, 45 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&ifaceCondition)), 46 action: wtFwpmAction0{ 47 _type: cFWP_ACTION_PERMIT, 48 }, 49 } 50 51 filterID := uint64(0) 52 53 // 54 // #1 Permit outbound IPv4 traffic. 55 // 56 { 57 displayData, err := createWtFwpmDisplayData0("Permit outbound IPv4 traffic on TUN", "") 58 if err != nil { 59 return wrapErr(err) 60 } 61 62 filter.displayData = *displayData 63 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 64 65 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 66 if err != nil { 67 return wrapErr(err) 68 } 69 } 70 71 // 72 // #2 Permit inbound IPv4 traffic. 73 // 74 { 75 displayData, err := createWtFwpmDisplayData0("Permit inbound IPv4 traffic on TUN", "") 76 if err != nil { 77 return wrapErr(err) 78 } 79 80 filter.displayData = *displayData 81 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 82 83 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 84 if err != nil { 85 return wrapErr(err) 86 } 87 } 88 89 // 90 // #3 Permit outbound IPv6 traffic. 91 // 92 { 93 displayData, err := createWtFwpmDisplayData0("Permit outbound IPv6 traffic on TUN", "") 94 if err != nil { 95 return wrapErr(err) 96 } 97 98 filter.displayData = *displayData 99 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 100 101 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 102 if err != nil { 103 return wrapErr(err) 104 } 105 } 106 107 // 108 // #4 Permit inbound IPv6 traffic. 109 // 110 { 111 displayData, err := createWtFwpmDisplayData0("Permit inbound IPv6 traffic on TUN", "") 112 if err != nil { 113 return wrapErr(err) 114 } 115 116 filter.displayData = *displayData 117 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 118 119 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 120 if err != nil { 121 return wrapErr(err) 122 } 123 } 124 125 return nil 126 } 127 128 func permitMystWireGuardService(session uintptr, baseObjects *baseObjects, weight uint8) error { 129 appID, err := getMystAppID() 130 if err != nil { 131 return wrapErr(err) 132 } 133 defer fwpmFreeMemory0(unsafe.Pointer(&appID)) 134 135 condition := wtFwpmFilterCondition0{ 136 fieldKey: cFWPM_CONDITION_ALE_APP_ID, 137 matchType: cFWP_MATCH_EQUAL, 138 conditionValue: wtFwpConditionValue0{ 139 _type: cFWP_BYTE_BLOB_TYPE, 140 value: uintptr(unsafe.Pointer(appID)), 141 }, 142 } 143 144 filter := &wtFwpmFilter0{ 145 providerKey: &baseObjects.provider, 146 subLayerKey: baseObjects.filters, 147 weight: filterWeight(weight), 148 flags: cFWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT, 149 numFilterConditions: 1, 150 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)), 151 action: wtFwpmAction0{ 152 _type: cFWP_ACTION_PERMIT, 153 }, 154 } 155 156 return permitWireGuardServiceCommon(filter, session, baseObjects, weight) 157 } 158 159 func permitSupervisorWireGuardService(session uintptr, baseObjects *baseObjects, weight uint8) error { 160 var conditions [2]wtFwpmFilterCondition0 161 162 // 163 // First condition is the exe path of the current process. 164 // 165 appID, err := getCurrentProcessAppID() 166 if err != nil { 167 return wrapErr(err) 168 } 169 defer fwpmFreeMemory0(unsafe.Pointer(&appID)) 170 171 conditions[0] = wtFwpmFilterCondition0{ 172 fieldKey: cFWPM_CONDITION_ALE_APP_ID, 173 matchType: cFWP_MATCH_EQUAL, 174 conditionValue: wtFwpConditionValue0{ 175 _type: cFWP_BYTE_BLOB_TYPE, 176 value: uintptr(unsafe.Pointer(appID)), 177 }, 178 } 179 180 // 181 // Second condition is the SECURITY_DESCRIPTOR of the current process. 182 // This prevents other processes hosted in the same exe from matching this filter. 183 // 184 sd, err := getCurrentProcessSecurityDescriptor() 185 if err != nil { 186 return wrapErr(err) 187 } 188 189 conditions[1] = wtFwpmFilterCondition0{ 190 fieldKey: cFWPM_CONDITION_ALE_USER_ID, 191 matchType: cFWP_MATCH_EQUAL, 192 conditionValue: wtFwpConditionValue0{ 193 _type: cFWP_SECURITY_DESCRIPTOR_TYPE, 194 value: uintptr(unsafe.Pointer(&wtFwpByteBlob{sd.Length(), (*byte)(unsafe.Pointer(sd))})), 195 }, 196 } 197 198 // 199 // Assemble the filter. 200 // 201 filter := &wtFwpmFilter0{ 202 providerKey: &baseObjects.provider, 203 subLayerKey: baseObjects.filters, 204 weight: filterWeight(weight), 205 flags: cFWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT, 206 numFilterConditions: uint32(len(conditions)), 207 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), 208 action: wtFwpmAction0{ 209 _type: cFWP_ACTION_PERMIT, 210 }, 211 } 212 213 return permitWireGuardServiceCommon(filter, session, baseObjects, weight) 214 } 215 216 func permitWireGuardServiceCommon(filter *wtFwpmFilter0, session uintptr, baseObjects *baseObjects, weight uint8) error { 217 filterID := uint64(0) 218 219 // 220 // #1 Permit outbound IPv4 traffic. 221 // 222 { 223 displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv4)", "") 224 if err != nil { 225 return wrapErr(err) 226 } 227 228 filter.displayData = *displayData 229 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 230 231 err = fwpmFilterAdd0(session, filter, 0, &filterID) 232 if err != nil { 233 return wrapErr(err) 234 } 235 } 236 237 // 238 // #2 Permit inbound IPv4 traffic. 239 // 240 { 241 displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv4)", "") 242 if err != nil { 243 return wrapErr(err) 244 } 245 246 filter.displayData = *displayData 247 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 248 249 err = fwpmFilterAdd0(session, filter, 0, &filterID) 250 if err != nil { 251 return wrapErr(err) 252 } 253 } 254 255 // 256 // #3 Permit outbound IPv6 traffic. 257 // 258 { 259 displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv6)", "") 260 if err != nil { 261 return wrapErr(err) 262 } 263 264 filter.displayData = *displayData 265 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 266 267 err = fwpmFilterAdd0(session, filter, 0, &filterID) 268 if err != nil { 269 return wrapErr(err) 270 } 271 } 272 273 // 274 // #4 Permit inbound IPv6 traffic. 275 // 276 { 277 displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv6)", "") 278 if err != nil { 279 return wrapErr(err) 280 } 281 282 filter.displayData = *displayData 283 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 284 285 err = fwpmFilterAdd0(session, filter, 0, &filterID) 286 if err != nil { 287 return wrapErr(err) 288 } 289 } 290 291 return nil 292 } 293 294 func permitLoopback(session uintptr, baseObjects *baseObjects, weight uint8) error { 295 condition := wtFwpmFilterCondition0{ 296 fieldKey: cFWPM_CONDITION_FLAGS, 297 matchType: cFWP_MATCH_FLAGS_ALL_SET, 298 conditionValue: wtFwpConditionValue0{ 299 _type: cFWP_UINT32, 300 value: uintptr(cFWP_CONDITION_FLAG_IS_LOOPBACK), 301 }, 302 } 303 304 filter := wtFwpmFilter0{ 305 providerKey: &baseObjects.provider, 306 subLayerKey: baseObjects.filters, 307 weight: filterWeight(weight), 308 numFilterConditions: 1, 309 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)), 310 action: wtFwpmAction0{ 311 _type: cFWP_ACTION_PERMIT, 312 }, 313 } 314 315 filterID := uint64(0) 316 317 // 318 // #1 Permit outbound IPv4 on loopback. 319 // 320 { 321 displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv4)", "") 322 if err != nil { 323 return wrapErr(err) 324 } 325 326 filter.displayData = *displayData 327 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 328 329 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 330 if err != nil { 331 return wrapErr(err) 332 } 333 } 334 335 // 336 // #2 Permit inbound IPv4 on loopback. 337 // 338 { 339 displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv4)", "") 340 if err != nil { 341 return wrapErr(err) 342 } 343 344 filter.displayData = *displayData 345 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 346 347 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 348 if err != nil { 349 return wrapErr(err) 350 } 351 } 352 353 // 354 // #3 Permit outbound IPv6 on loopback. 355 // 356 { 357 displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv6)", "") 358 if err != nil { 359 return wrapErr(err) 360 } 361 362 filter.displayData = *displayData 363 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 364 365 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 366 if err != nil { 367 return wrapErr(err) 368 } 369 } 370 371 // 372 // #4 Permit inbound IPv6 on loopback. 373 // 374 { 375 displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv6)", "") 376 if err != nil { 377 return wrapErr(err) 378 } 379 380 filter.displayData = *displayData 381 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 382 383 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 384 if err != nil { 385 return wrapErr(err) 386 } 387 } 388 389 return nil 390 } 391 392 func permitDHCPIPv4(session uintptr, baseObjects *baseObjects, weight uint8) error { 393 // 394 // #1 Outbound DHCP request on IPv4. 395 // 396 { 397 var conditions [4]wtFwpmFilterCondition0 398 399 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 400 conditions[0].matchType = cFWP_MATCH_EQUAL 401 conditions[0].conditionValue._type = cFWP_UINT8 402 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) 403 404 conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT 405 conditions[1].matchType = cFWP_MATCH_EQUAL 406 conditions[1].conditionValue._type = cFWP_UINT16 407 conditions[1].conditionValue.value = uintptr(68) 408 409 conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT 410 conditions[2].matchType = cFWP_MATCH_EQUAL 411 conditions[2].conditionValue._type = cFWP_UINT16 412 conditions[2].conditionValue.value = uintptr(67) 413 414 conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 415 conditions[3].matchType = cFWP_MATCH_EQUAL 416 conditions[3].conditionValue._type = cFWP_UINT32 417 conditions[3].conditionValue.value = uintptr(0xffffffff) 418 419 displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv4)", "") 420 if err != nil { 421 return wrapErr(err) 422 } 423 424 filter := wtFwpmFilter0{ 425 displayData: *displayData, 426 providerKey: &baseObjects.provider, 427 layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V4, 428 subLayerKey: baseObjects.filters, 429 weight: filterWeight(weight), 430 numFilterConditions: uint32(len(conditions)), 431 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), 432 action: wtFwpmAction0{ 433 _type: cFWP_ACTION_PERMIT, 434 }, 435 } 436 437 filterID := uint64(0) 438 439 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 440 if err != nil { 441 return wrapErr(err) 442 } 443 } 444 445 // 446 // #2 Inbound DHCP response on IPv4. 447 // 448 { 449 var conditions [3]wtFwpmFilterCondition0 450 451 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 452 conditions[0].matchType = cFWP_MATCH_EQUAL 453 conditions[0].conditionValue._type = cFWP_UINT8 454 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) 455 456 conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT 457 conditions[1].matchType = cFWP_MATCH_EQUAL 458 conditions[1].conditionValue._type = cFWP_UINT16 459 conditions[1].conditionValue.value = uintptr(68) 460 461 conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT 462 conditions[2].matchType = cFWP_MATCH_EQUAL 463 conditions[2].conditionValue._type = cFWP_UINT16 464 conditions[2].conditionValue.value = uintptr(67) 465 466 displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv4)", "") 467 if err != nil { 468 return wrapErr(err) 469 } 470 471 filter := wtFwpmFilter0{ 472 displayData: *displayData, 473 providerKey: &baseObjects.provider, 474 layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, 475 subLayerKey: baseObjects.filters, 476 weight: filterWeight(weight), 477 numFilterConditions: uint32(len(conditions)), 478 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), 479 action: wtFwpmAction0{ 480 _type: cFWP_ACTION_PERMIT, 481 }, 482 } 483 484 filterID := uint64(0) 485 486 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 487 if err != nil { 488 return wrapErr(err) 489 } 490 } 491 492 return nil 493 } 494 495 func permitDHCPIPv6(session uintptr, baseObjects *baseObjects, weight uint8) error { 496 // 497 // #1 Outbound DHCP request on IPv6. 498 // 499 { 500 var conditions [6]wtFwpmFilterCondition0 501 502 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 503 conditions[0].matchType = cFWP_MATCH_EQUAL 504 conditions[0].conditionValue._type = cFWP_UINT8 505 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) 506 507 conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 508 conditions[1].matchType = cFWP_MATCH_EQUAL 509 conditions[1].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE 510 conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&linkLocalDHCPMulticast)) 511 512 // Repeat the condition type for logical OR. 513 conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 514 conditions[2].matchType = cFWP_MATCH_EQUAL 515 conditions[2].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE 516 conditions[2].conditionValue.value = uintptr(unsafe.Pointer(&siteLocalDHCPMulticast)) 517 518 conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT 519 conditions[3].matchType = cFWP_MATCH_EQUAL 520 conditions[3].conditionValue._type = cFWP_UINT16 521 conditions[3].conditionValue.value = uintptr(547) 522 523 conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS 524 conditions[4].matchType = cFWP_MATCH_EQUAL 525 conditions[4].conditionValue._type = cFWP_V6_ADDR_MASK 526 conditions[4].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) 527 528 conditions[5].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT 529 conditions[5].matchType = cFWP_MATCH_EQUAL 530 conditions[5].conditionValue._type = cFWP_UINT16 531 conditions[5].conditionValue.value = uintptr(546) 532 533 displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv6)", "") 534 if err != nil { 535 return wrapErr(err) 536 } 537 538 filter := wtFwpmFilter0{ 539 displayData: *displayData, 540 providerKey: &baseObjects.provider, 541 layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, 542 subLayerKey: baseObjects.filters, 543 weight: filterWeight(weight), 544 numFilterConditions: uint32(len(conditions)), 545 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), 546 action: wtFwpmAction0{ 547 _type: cFWP_ACTION_PERMIT, 548 }, 549 } 550 551 filterID := uint64(0) 552 553 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 554 if err != nil { 555 return wrapErr(err) 556 } 557 } 558 559 // 560 // #2 Inbound DHCP response on IPv6. 561 // 562 { 563 var conditions [5]wtFwpmFilterCondition0 564 565 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 566 conditions[0].matchType = cFWP_MATCH_EQUAL 567 conditions[0].conditionValue._type = cFWP_UINT8 568 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) 569 570 conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 571 conditions[1].matchType = cFWP_MATCH_EQUAL 572 conditions[1].conditionValue._type = cFWP_V6_ADDR_MASK 573 conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) 574 575 conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT 576 conditions[2].matchType = cFWP_MATCH_EQUAL 577 conditions[2].conditionValue._type = cFWP_UINT16 578 conditions[2].conditionValue.value = uintptr(547) 579 580 conditions[3].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS 581 conditions[3].matchType = cFWP_MATCH_EQUAL 582 conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK 583 conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) 584 585 conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT 586 conditions[4].matchType = cFWP_MATCH_EQUAL 587 conditions[4].conditionValue._type = cFWP_UINT16 588 conditions[4].conditionValue.value = uintptr(546) 589 590 displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv6)", "") 591 if err != nil { 592 return wrapErr(err) 593 } 594 595 filter := wtFwpmFilter0{ 596 displayData: *displayData, 597 providerKey: &baseObjects.provider, 598 layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, 599 subLayerKey: baseObjects.filters, 600 weight: filterWeight(weight), 601 numFilterConditions: uint32(len(conditions)), 602 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), 603 action: wtFwpmAction0{ 604 _type: cFWP_ACTION_PERMIT, 605 }, 606 } 607 608 filterID := uint64(0) 609 610 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 611 if err != nil { 612 return wrapErr(err) 613 } 614 } 615 616 return nil 617 } 618 619 func permitNdp(session uintptr, baseObjects *baseObjects, weight uint8) error { 620 /* TODO: actually handle the hop limit somehow! The rules should vaguely be: 621 * - icmpv6 133: must be outgoing, dst must be FF02::2/128, hop limit must be 255 622 * - icmpv6 134: must be incoming, src must be FE80::/10, hop limit must be 255 623 * - icmpv6 135: either incoming or outgoing, hop limit must be 255 624 * - icmpv6 136: either incoming or outgoing, hop limit must be 255 625 * - icmpv6 137: must be incoming, src must be FE80::/10, hop limit must be 255 626 */ 627 628 type filterDefinition struct { 629 displayData *wtFwpmDisplayData0 630 conditions []wtFwpmFilterCondition0 631 layer windows.GUID 632 } 633 634 var defs []filterDefinition 635 636 // 637 // Router Solicitation Message 638 // ICMP type 133, code 0. Outgoing. 639 // 640 { 641 conditions := make([]wtFwpmFilterCondition0, 4) 642 643 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 644 conditions[0].matchType = cFWP_MATCH_EQUAL 645 conditions[0].conditionValue._type = cFWP_UINT8 646 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMPV6) 647 648 conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE 649 conditions[1].matchType = cFWP_MATCH_EQUAL 650 conditions[1].conditionValue._type = cFWP_UINT16 651 conditions[1].conditionValue.value = uintptr(133) 652 653 conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE 654 conditions[2].matchType = cFWP_MATCH_EQUAL 655 conditions[2].conditionValue._type = cFWP_UINT16 656 conditions[2].conditionValue.value = uintptr(0) 657 658 conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 659 conditions[3].matchType = cFWP_MATCH_EQUAL 660 conditions[3].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE 661 conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocalRouterMulticast)) 662 663 displayData, err := createWtFwpmDisplayData0("Permit NDP type 133", "") 664 if err != nil { 665 return wrapErr(err) 666 } 667 668 defs = append(defs, filterDefinition{ 669 displayData: displayData, 670 conditions: conditions, 671 layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, 672 }) 673 } 674 675 // 676 // Router Advertisement Message 677 // ICMP type 134, code 0. Incoming. 678 // 679 { 680 conditions := make([]wtFwpmFilterCondition0, 4) 681 682 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 683 conditions[0].matchType = cFWP_MATCH_EQUAL 684 conditions[0].conditionValue._type = cFWP_UINT8 685 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMPV6) 686 687 conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE 688 conditions[1].matchType = cFWP_MATCH_EQUAL 689 conditions[1].conditionValue._type = cFWP_UINT16 690 conditions[1].conditionValue.value = uintptr(134) 691 692 conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE 693 conditions[2].matchType = cFWP_MATCH_EQUAL 694 conditions[2].conditionValue._type = cFWP_UINT16 695 conditions[2].conditionValue.value = uintptr(0) 696 697 conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 698 conditions[3].matchType = cFWP_MATCH_EQUAL 699 conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK 700 conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) 701 702 displayData, err := createWtFwpmDisplayData0("Permit NDP type 134", "") 703 if err != nil { 704 return wrapErr(err) 705 } 706 707 defs = append(defs, filterDefinition{ 708 displayData: displayData, 709 conditions: conditions, 710 layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, 711 }) 712 } 713 714 // 715 // Neighbor Solicitation Message 716 // ICMP type 135, code 0. Bi-directional. 717 // 718 { 719 conditions := make([]wtFwpmFilterCondition0, 3) 720 721 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 722 conditions[0].matchType = cFWP_MATCH_EQUAL 723 conditions[0].conditionValue._type = cFWP_UINT8 724 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMPV6) 725 726 conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE 727 conditions[1].matchType = cFWP_MATCH_EQUAL 728 conditions[1].conditionValue._type = cFWP_UINT16 729 conditions[1].conditionValue.value = uintptr(135) 730 731 conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE 732 conditions[2].matchType = cFWP_MATCH_EQUAL 733 conditions[2].conditionValue._type = cFWP_UINT16 734 conditions[2].conditionValue.value = uintptr(0) 735 736 displayData, err := createWtFwpmDisplayData0("Permit NDP type 135", "") 737 if err != nil { 738 return wrapErr(err) 739 } 740 741 defs = append(defs, filterDefinition{ 742 displayData: displayData, 743 conditions: conditions, 744 layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, 745 }) 746 747 defs = append(defs, filterDefinition{ 748 displayData: displayData, 749 conditions: conditions, 750 layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, 751 }) 752 } 753 754 // 755 // Neighbor Advertisement Message 756 // ICMP type 136, code 0. Bi-directional. 757 // 758 { 759 conditions := make([]wtFwpmFilterCondition0, 3) 760 761 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 762 conditions[0].matchType = cFWP_MATCH_EQUAL 763 conditions[0].conditionValue._type = cFWP_UINT8 764 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMPV6) 765 766 conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE 767 conditions[1].matchType = cFWP_MATCH_EQUAL 768 conditions[1].conditionValue._type = cFWP_UINT16 769 conditions[1].conditionValue.value = uintptr(136) 770 771 conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE 772 conditions[2].matchType = cFWP_MATCH_EQUAL 773 conditions[2].conditionValue._type = cFWP_UINT16 774 conditions[2].conditionValue.value = uintptr(0) 775 776 displayData, err := createWtFwpmDisplayData0("Permit NDP type 136", "") 777 if err != nil { 778 return wrapErr(err) 779 } 780 781 defs = append(defs, filterDefinition{ 782 displayData: displayData, 783 conditions: conditions, 784 layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, 785 }) 786 787 defs = append(defs, filterDefinition{ 788 displayData: displayData, 789 conditions: conditions, 790 layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, 791 }) 792 } 793 794 // 795 // Redirect Message 796 // ICMP type 137, code 0. Incoming. 797 // 798 { 799 conditions := make([]wtFwpmFilterCondition0, 4) 800 801 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL 802 conditions[0].matchType = cFWP_MATCH_EQUAL 803 conditions[0].conditionValue._type = cFWP_UINT8 804 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMPV6) 805 806 conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE 807 conditions[1].matchType = cFWP_MATCH_EQUAL 808 conditions[1].conditionValue._type = cFWP_UINT16 809 conditions[1].conditionValue.value = uintptr(137) 810 811 conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE 812 conditions[2].matchType = cFWP_MATCH_EQUAL 813 conditions[2].conditionValue._type = cFWP_UINT16 814 conditions[2].conditionValue.value = uintptr(0) 815 816 conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS 817 conditions[3].matchType = cFWP_MATCH_EQUAL 818 conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK 819 conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) 820 821 displayData, err := createWtFwpmDisplayData0("Permit NDP type 137", "") 822 if err != nil { 823 return wrapErr(err) 824 } 825 826 defs = append(defs, filterDefinition{ 827 displayData: displayData, 828 conditions: conditions, 829 layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, 830 }) 831 } 832 833 filter := wtFwpmFilter0{ 834 providerKey: &baseObjects.provider, 835 subLayerKey: baseObjects.filters, 836 weight: filterWeight(weight), 837 action: wtFwpmAction0{ 838 _type: cFWP_ACTION_PERMIT, 839 }, 840 } 841 842 filterID := uint64(0) 843 844 for _, definition := range defs { 845 filter.displayData = *definition.displayData 846 filter.layerKey = definition.layer 847 filter.numFilterConditions = uint32(len(definition.conditions)) 848 filter.filterCondition = (*wtFwpmFilterCondition0)(unsafe.Pointer(&definition.conditions[0])) 849 850 err := fwpmFilterAdd0(session, &filter, 0, &filterID) 851 if err != nil { 852 return wrapErr(err) 853 } 854 } 855 856 return nil 857 } 858 859 func permitHyperV(session uintptr, baseObjects *baseObjects, weight uint8) error { 860 // 861 // Only applicable on Win8+. 862 // 863 { 864 major, minor, _ := windows.RtlGetNtVersionNumbers() 865 win8plus := major > 6 || (major == 6 && minor >= 3) 866 867 if !win8plus { 868 return nil 869 } 870 } 871 872 condition := wtFwpmFilterCondition0{ 873 fieldKey: cFWPM_CONDITION_L2_FLAGS, 874 matchType: cFWP_MATCH_EQUAL, 875 conditionValue: wtFwpConditionValue0{ 876 _type: cFWP_UINT32, 877 value: uintptr(cFWP_CONDITION_L2_IS_VM2VM), 878 }, 879 } 880 881 filter := wtFwpmFilter0{ 882 providerKey: &baseObjects.provider, 883 subLayerKey: baseObjects.filters, 884 weight: filterWeight(weight), 885 numFilterConditions: 1, 886 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)), 887 action: wtFwpmAction0{ 888 _type: cFWP_ACTION_PERMIT, 889 }, 890 } 891 892 filterID := uint64(0) 893 894 // 895 // #1 Outbound. 896 // 897 { 898 displayData, err := createWtFwpmDisplayData0("Permit Hyper-V => Hyper-V outbound", "") 899 if err != nil { 900 return wrapErr(err) 901 } 902 903 filter.displayData = *displayData 904 filter.layerKey = cFWPM_LAYER_OUTBOUND_MAC_FRAME_NATIVE 905 906 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 907 if err != nil { 908 return wrapErr(err) 909 } 910 } 911 912 // 913 // #2 Inbound. 914 // 915 { 916 displayData, err := createWtFwpmDisplayData0("Permit Hyper-V => Hyper-V inbound", "") 917 if err != nil { 918 return wrapErr(err) 919 } 920 921 filter.displayData = *displayData 922 filter.layerKey = cFWPM_LAYER_INBOUND_MAC_FRAME_NATIVE 923 924 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 925 if err != nil { 926 return wrapErr(err) 927 } 928 } 929 930 return nil 931 } 932 933 // Block all traffic except what is explicitly permitted by other rules. 934 func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { 935 filter := wtFwpmFilter0{ 936 providerKey: &baseObjects.provider, 937 subLayerKey: baseObjects.filters, 938 weight: filterWeight(weight), 939 action: wtFwpmAction0{ 940 _type: cFWP_ACTION_BLOCK, 941 }, 942 } 943 944 filterID := uint64(0) 945 946 // 947 // #1 Block outbound traffic on IPv4. 948 // 949 { 950 displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv4)", "") 951 if err != nil { 952 return wrapErr(err) 953 } 954 955 filter.displayData = *displayData 956 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 957 958 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 959 if err != nil { 960 return wrapErr(err) 961 } 962 } 963 964 // 965 // #2 Block inbound traffic on IPv4. 966 // 967 { 968 displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv4)", "") 969 if err != nil { 970 return wrapErr(err) 971 } 972 973 filter.displayData = *displayData 974 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 975 976 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 977 if err != nil { 978 return wrapErr(err) 979 } 980 } 981 982 // 983 // #3 Block outbound traffic on IPv6. 984 // 985 { 986 displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv6)", "") 987 if err != nil { 988 return wrapErr(err) 989 } 990 991 filter.displayData = *displayData 992 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 993 994 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 995 if err != nil { 996 return wrapErr(err) 997 } 998 } 999 1000 // 1001 // #4 Block inbound traffic on IPv6. 1002 // 1003 { 1004 displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv6)", "") 1005 if err != nil { 1006 return wrapErr(err) 1007 } 1008 1009 filter.displayData = *displayData 1010 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 1011 1012 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1013 if err != nil { 1014 return wrapErr(err) 1015 } 1016 } 1017 1018 return nil 1019 } 1020 1021 // Block all DNS traffic except towards specified DNS servers. 1022 func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weightAllow uint8, weightDeny uint8) error { 1023 if weightDeny >= weightAllow { 1024 return errors.New("The allow weight must be greater than the deny weight") 1025 } 1026 1027 denyConditions := []wtFwpmFilterCondition0{ 1028 { 1029 fieldKey: cFWPM_CONDITION_IP_REMOTE_PORT, 1030 matchType: cFWP_MATCH_EQUAL, 1031 conditionValue: wtFwpConditionValue0{ 1032 _type: cFWP_UINT16, 1033 value: uintptr(53), 1034 }, 1035 }, 1036 { 1037 fieldKey: cFWPM_CONDITION_IP_PROTOCOL, 1038 matchType: cFWP_MATCH_EQUAL, 1039 conditionValue: wtFwpConditionValue0{ 1040 _type: cFWP_UINT8, 1041 value: uintptr(cIPPROTO_UDP), 1042 }, 1043 }, 1044 // Repeat the condition type for logical OR. 1045 { 1046 fieldKey: cFWPM_CONDITION_IP_PROTOCOL, 1047 matchType: cFWP_MATCH_EQUAL, 1048 conditionValue: wtFwpConditionValue0{ 1049 _type: cFWP_UINT8, 1050 value: uintptr(cIPPROTO_TCP), 1051 }, 1052 }, 1053 } 1054 1055 filter := wtFwpmFilter0{ 1056 providerKey: &baseObjects.provider, 1057 subLayerKey: baseObjects.filters, 1058 weight: filterWeight(weightDeny), 1059 numFilterConditions: uint32(len(denyConditions)), 1060 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&denyConditions[0])), 1061 action: wtFwpmAction0{ 1062 _type: cFWP_ACTION_BLOCK, 1063 }, 1064 } 1065 1066 filterID := uint64(0) 1067 1068 // 1069 // #1 Block IPv4 outbound DNS. 1070 // 1071 { 1072 displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv4)", "") 1073 if err != nil { 1074 return wrapErr(err) 1075 } 1076 1077 filter.displayData = *displayData 1078 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 1079 1080 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1081 if err != nil { 1082 return wrapErr(err) 1083 } 1084 } 1085 1086 // 1087 // #2 Block IPv4 inbound DNS. 1088 // 1089 { 1090 displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv4)", "") 1091 if err != nil { 1092 return wrapErr(err) 1093 } 1094 1095 filter.displayData = *displayData 1096 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 1097 1098 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1099 if err != nil { 1100 return wrapErr(err) 1101 } 1102 } 1103 1104 // 1105 // #3 Block IPv6 outbound DNS. 1106 // 1107 { 1108 displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv6)", "") 1109 if err != nil { 1110 return wrapErr(err) 1111 } 1112 1113 filter.displayData = *displayData 1114 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 1115 1116 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1117 if err != nil { 1118 return wrapErr(err) 1119 } 1120 } 1121 1122 // 1123 // #4 Block IPv6 inbound DNS. 1124 // 1125 { 1126 displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv6)", "") 1127 if err != nil { 1128 return wrapErr(err) 1129 } 1130 1131 filter.displayData = *displayData 1132 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 1133 1134 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1135 if err != nil { 1136 return wrapErr(err) 1137 } 1138 } 1139 1140 allowConditionsV4 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except)) 1141 allowConditionsV4 = append(allowConditionsV4, denyConditions...) 1142 for _, ip := range except { 1143 ip4 := ip.To4() 1144 if ip4 == nil { 1145 continue 1146 } 1147 allowConditionsV4 = append(allowConditionsV4, wtFwpmFilterCondition0{ 1148 fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS, 1149 matchType: cFWP_MATCH_EQUAL, 1150 conditionValue: wtFwpConditionValue0{ 1151 _type: cFWP_UINT32, 1152 value: uintptr(binary.BigEndian.Uint32(ip4)), 1153 }, 1154 }) 1155 } 1156 1157 storedPointers := make([]*wtFwpByteArray16, 0, len(except)) 1158 allowConditionsV6 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except)) 1159 allowConditionsV6 = append(allowConditionsV6, denyConditions...) 1160 for _, ip := range except { 1161 if ip.To4() != nil { 1162 continue 1163 } 1164 var address wtFwpByteArray16 1165 copy(address.byteArray16[:], ip) 1166 allowConditionsV6 = append(allowConditionsV6, wtFwpmFilterCondition0{ 1167 fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS, 1168 matchType: cFWP_MATCH_EQUAL, 1169 conditionValue: wtFwpConditionValue0{ 1170 _type: cFWP_BYTE_ARRAY16_TYPE, 1171 value: uintptr(unsafe.Pointer(&address)), 1172 }, 1173 }) 1174 storedPointers = append(storedPointers, &address) 1175 } 1176 1177 filter = wtFwpmFilter0{ 1178 providerKey: &baseObjects.provider, 1179 subLayerKey: baseObjects.filters, 1180 weight: filterWeight(weightAllow), 1181 numFilterConditions: uint32(len(allowConditionsV4)), 1182 filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&allowConditionsV4[0])), 1183 action: wtFwpmAction0{ 1184 _type: cFWP_ACTION_PERMIT, 1185 }, 1186 } 1187 1188 filterID = uint64(0) 1189 1190 // 1191 // #5 Allow IPv4 outbound DNS. 1192 // 1193 if len(allowConditionsV4) > len(denyConditions) { 1194 displayData, err := createWtFwpmDisplayData0("Allow DNS outbound (IPv4)", "") 1195 if err != nil { 1196 return wrapErr(err) 1197 } 1198 1199 filter.displayData = *displayData 1200 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 1201 1202 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1203 if err != nil { 1204 return wrapErr(err) 1205 } 1206 } 1207 1208 // 1209 // #6 Allow IPv4 inbound DNS. 1210 // 1211 if len(allowConditionsV4) > len(denyConditions) { 1212 displayData, err := createWtFwpmDisplayData0("Allow DNS inbound (IPv4)", "") 1213 if err != nil { 1214 return wrapErr(err) 1215 } 1216 1217 filter.displayData = *displayData 1218 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 1219 1220 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1221 if err != nil { 1222 return wrapErr(err) 1223 } 1224 } 1225 1226 filter.filterCondition = (*wtFwpmFilterCondition0)(unsafe.Pointer(&allowConditionsV6[0])) 1227 filter.numFilterConditions = uint32(len(allowConditionsV6)) 1228 1229 // 1230 // #7 Allow IPv6 outbound DNS. 1231 // 1232 if len(allowConditionsV6) > len(denyConditions) { 1233 displayData, err := createWtFwpmDisplayData0("Allow DNS outbound (IPv6)", "") 1234 if err != nil { 1235 return wrapErr(err) 1236 } 1237 1238 filter.displayData = *displayData 1239 filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 1240 1241 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1242 if err != nil { 1243 return wrapErr(err) 1244 } 1245 } 1246 1247 // 1248 // #8 Allow IPv6 inbound DNS. 1249 // 1250 if len(allowConditionsV6) > len(denyConditions) { 1251 displayData, err := createWtFwpmDisplayData0("Allow DNS inbound (IPv6)", "") 1252 if err != nil { 1253 return wrapErr(err) 1254 } 1255 1256 filter.displayData = *displayData 1257 filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 1258 1259 err = fwpmFilterAdd0(session, &filter, 0, &filterID) 1260 if err != nil { 1261 return wrapErr(err) 1262 } 1263 } 1264 1265 runtime.KeepAlive(storedPointers) 1266 1267 return nil 1268 }