/* SPDX-License-Identifier: MIT * * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. */ package firewall import ( "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/version" "unsafe" ) // // Known addresses. // var ( linkLocal = wtFwpV6AddrAndMask{[16]uint8{0xfe, 0x80}, 10} linkLocalDhcpMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2}} siteLocalDhcpMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x3}} linkLocalRouterMulticast = wtFwpByteArray16{[16]uint8{0xFF, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}} ) func permitTunInterface(session uintptr, baseObjects *baseObjects, weight uint8, ifLuid uint64) error { ifaceCondition := wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_IP_LOCAL_INTERFACE, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT64, value: (uintptr)(unsafe.Pointer(&ifLuid)), }, } filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: 1, filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&ifaceCondition)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) // // #1 Permit outbound IPv4 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit outbound IPv4 traffic on TUN", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Permit inbound IPv4 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit inbound IPv4 traffic on TUN", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #3 Permit outbound IPv6 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit outbound IPv6 traffic on TUN", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #4 Permit inbound IPv6 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit inbound IPv6 traffic on TUN", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitWireGuardService(session uintptr, baseObjects *baseObjects, weight uint8) error { var conditions [2]wtFwpmFilterCondition0 // // First condition is the exe path of the current process. // appId, err := getCurrentProcessAppId() if err != nil { return wrapErr(err) } defer fwpmFreeMemory0(unsafe.Pointer(&appId)) conditions[0] = wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_ALE_APP_ID, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_BYTE_BLOB_TYPE, value: uintptr(unsafe.Pointer(appId)), }, } // // Second condition is the SECURITY_DESCRIPTOR of the current process. // This prevents low privileged applications hosted in the same exe from matching this filter. // sd, err := getCurrentProcessSecurityDescriptor() if err != nil { return wrapErr(err) } defer windows.LocalFree(windows.Handle(unsafe.Pointer(sd.data))) conditions[1] = wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_ALE_USER_ID, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_SECURITY_DESCRIPTOR_TYPE, value: uintptr(unsafe.Pointer(sd)), }, } // // Assemble the filter. // filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) // // #1 Permit outbound IPv4 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Permit inbound IPv4 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #3 Permit outbound IPv6 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #4 Permit inbound IPv6 traffic. // { displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitLoopback(session uintptr, baseObjects *baseObjects, weight uint8) error { condition := wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_INTERFACE_TYPE, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT32, value: uintptr(cIF_TYPE_SOFTWARE_LOOPBACK), }, } filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: 1, filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) // // #1 Permit outbound IPv4 on loopback. // { displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Permit inbound IPv4 on loopback. // { displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #3 Permit outbound IPv6 on loopback. // { displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #4 Permit inbound IPv6 on loopback. // { displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitDhcpIpv4(session uintptr, baseObjects *baseObjects, weight uint8) error { // // #1 Outbound DHCP request on IPv4. // { var conditions [4]wtFwpmFilterCondition0 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(68) conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(67) conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_UINT32 conditions[3].conditionValue.value = uintptr(0xffffffff) displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv4)", "") if err != nil { return wrapErr(err) } filter := wtFwpmFilter0{ displayData: *displayData, providerKey: &baseObjects.provider, layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V4, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Inbound DHCP response on IPv4. // { var conditions [3]wtFwpmFilterCondition0 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(68) conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(67) displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv4)", "") if err != nil { return wrapErr(err) } filter := wtFwpmFilter0{ displayData: *displayData, providerKey: &baseObjects.provider, layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitDhcpIpv6(session uintptr, baseObjects *baseObjects, weight uint8) error { // // #1 Outbound DHCP request on IPv6. // { var conditions [6]wtFwpmFilterCondition0 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&linkLocalDhcpMulticast)) // Repeat the condition type for logical OR. conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE conditions[2].conditionValue.value = uintptr(unsafe.Pointer(&siteLocalDhcpMulticast)) conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_UINT16 conditions[3].conditionValue.value = uintptr(547) conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS conditions[4].matchType = cFWP_MATCH_EQUAL conditions[4].conditionValue._type = cFWP_V6_ADDR_MASK conditions[4].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) conditions[5].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT conditions[5].matchType = cFWP_MATCH_EQUAL conditions[5].conditionValue._type = cFWP_UINT16 conditions[5].conditionValue.value = uintptr(546) displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv6)", "") if err != nil { return wrapErr(err) } filter := wtFwpmFilter0{ displayData: *displayData, providerKey: &baseObjects.provider, layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Inbound DHCP response on IPv6. // { var conditions [5]wtFwpmFilterCondition0 conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP) conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_V6_ADDR_MASK conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(547) conditions[3].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT conditions[4].matchType = cFWP_MATCH_EQUAL conditions[4].conditionValue._type = cFWP_UINT16 conditions[4].conditionValue.value = uintptr(546) displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv6)", "") if err != nil { return wrapErr(err) } filter := wtFwpmFilter0{ displayData: *displayData, providerKey: &baseObjects.provider, layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitNdp(session uintptr, baseObjects *baseObjects, weight uint8) error { /* TODO: actually handle the hop limit somehow! The rules should vaguely be: * - icmpv6 133: must be outgoing, dst must be FF02::2/128, hop limit must be 255 * - icmpv6 134: must be incoming, src must be FE80::/10, hop limit must be 255 * - icmpv6 135: either incoming or outgoing, hop limit must be 255 * - icmpv6 136: either incoming or outgoing, hop limit must be 255 * - icmpv6 137: must be incoming, src must be FE80::/10, hop limit must be 255 */ type filterDefinition struct { displayData *wtFwpmDisplayData0 conditions []wtFwpmFilterCondition0 layer windows.GUID } var defs []filterDefinition // // Router Solicitation Message // ICMP type 133, code 0. Outgoing. // { conditions := make([]wtFwpmFilterCondition0, 4) conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP) conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(133) conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(0) conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocalRouterMulticast)) displayData, err := createWtFwpmDisplayData0("Permit NDP type 133", "") if err != nil { return wrapErr(err) } defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, }) } // // Router Advertisement Message // ICMP type 134, code 0. Incoming. // { conditions := make([]wtFwpmFilterCondition0, 4) conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP) conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(134) conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(0) conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) displayData, err := createWtFwpmDisplayData0("Permit NDP type 134", "") if err != nil { return wrapErr(err) } defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, }) } // // Neighbor Solicitation Message // ICMP type 135, code 0. Bi-directional. // { conditions := make([]wtFwpmFilterCondition0, 3) conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP) conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(135) conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(0) displayData, err := createWtFwpmDisplayData0("Permit NDP type 135", "") if err != nil { return wrapErr(err) } defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, }) defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, }) } // // Neighbor Advertisement Message // ICMP type 136, code 0. Bi-directional. // { conditions := make([]wtFwpmFilterCondition0, 3) conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP) conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(136) conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(0) displayData, err := createWtFwpmDisplayData0("Permit NDP type 136", "") if err != nil { return wrapErr(err) } defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_CONNECT_V6, }) defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, }) } // // Redirect Message // ICMP type 137, code 0. Incoming. // { conditions := make([]wtFwpmFilterCondition0, 4) conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL conditions[0].matchType = cFWP_MATCH_EQUAL conditions[0].conditionValue._type = cFWP_UINT8 conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP) conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE conditions[1].matchType = cFWP_MATCH_EQUAL conditions[1].conditionValue._type = cFWP_UINT16 conditions[1].conditionValue.value = uintptr(137) conditions[2].fieldKey = cFWPM_CONDITION_ICMP_CODE conditions[2].matchType = cFWP_MATCH_EQUAL conditions[2].conditionValue._type = cFWP_UINT16 conditions[2].conditionValue.value = uintptr(0) conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS conditions[3].matchType = cFWP_MATCH_EQUAL conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&linkLocal)) displayData, err := createWtFwpmDisplayData0("Permit NDP type 137", "") if err != nil { return wrapErr(err) } defs = append(defs, filterDefinition{ displayData: displayData, conditions: conditions, layer: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, }) } filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) for _, definition := range defs { filter.displayData = *definition.displayData filter.layerKey = definition.layer filter.numFilterConditions = uint32(len(definition.conditions)) filter.filterCondition = (*wtFwpmFilterCondition0)(unsafe.Pointer(&definition.conditions[0])) err := fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } func permitHyperV(session uintptr, baseObjects *baseObjects, weight uint8) error { // // Only applicable on Win8+. // { v, err := version.OsVersion() if err != nil { panic(err) } win8plus := v.MajorVersion > 6 || (v.MajorVersion == 6 && v.MinorVersion >= 3) if !win8plus { return nil } } condition := wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_L2_FLAGS, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT32, value: uintptr(cFWP_CONDITION_L2_IS_VM2VM), }, } filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: 1, filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } filterId := uint64(0) // // #1 Outbound. // { displayData, err := createWtFwpmDisplayData0("Permit Hyper-V => Hyper-V outbound", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_OUTBOUND_MAC_FRAME_NATIVE err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Inbound. // { displayData, err := createWtFwpmDisplayData0("Permit Hyper-V => Hyper-V inbound", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_INBOUND_MAC_FRAME_NATIVE err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } // Block all traffic except what is explicitly permitted by other rules. func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), action: wtFwpmAction0{ _type: cFWP_ACTION_BLOCK, }, } filterId := uint64(0) // // #1 Block outbound traffic on IPv4. // { displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Block inbound traffic on IPv4. // { displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #3 Block outbound traffic on IPv6. // { displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #4 Block inbound traffic on IPv6. // { displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil } // Block all DNS except what is matched by a permissive rule. func blockDns(session uintptr, baseObjects *baseObjects, weight uint8) error { var conditions [3]wtFwpmFilterCondition0 conditions[0] = wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_IP_REMOTE_PORT, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT16, value: uintptr(53), }, } conditions[1] = wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_IP_PROTOCOL, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT8, value: uintptr(cIPPROTO_UDP), }, } // Repeat the condition type for logical OR. conditions[2] = wtFwpmFilterCondition0{ fieldKey: cFWPM_CONDITION_IP_PROTOCOL, matchType: cFWP_MATCH_EQUAL, conditionValue: wtFwpConditionValue0{ _type: cFWP_UINT8, value: uintptr(cIPPROTO_TCP), }, } filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, weight: filterWeight(weight), numFilterConditions: uint32(len(conditions)), filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions[0])), action: wtFwpmAction0{ _type: cFWP_ACTION_BLOCK, }, } filterId := uint64(0) // // #1 Block IPv4 outbound DNS. // { displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #2 Block IPv4 inbound DNS. // { displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv4)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #3 Block IPv6 outbound DNS. // { displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } // // #4 Block IPv6 inbound DNS. // { displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv6)", "") if err != nil { return wrapErr(err) } filter.displayData = *displayData filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 err = fwpmFilterAdd0(session, &filter, 0, &filterId) if err != nil { return wrapErr(err) } } return nil }