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