diff options
Diffstat (limited to 'tunnel/firewall/rules.go')
-rw-r--r-- | tunnel/firewall/rules.go | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/tunnel/firewall/rules.go b/tunnel/firewall/rules.go index 41632f98..4788b0e2 100644 --- a/tunnel/firewall/rules.go +++ b/tunnel/firewall/rules.go @@ -581,6 +581,19 @@ func permitDHCPIPv6(session uintptr, baseObjects *baseObjects, weight uint8) err return nil } +func setFilterConditions(filter *wtFwpmFilter0, conditions []wtFwpmFilterCondition0) { + if uint(len(conditions)) > uint(^uint32(0)) { + panic("number of filter conditions out of bounds") + } + if len(conditions) > 0 { + filter.numFilterConditions = uint32(len(conditions)) + filter.filterCondition = (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions[0])) + return + } + filter.numFilterConditions = 0 + filter.filterCondition = 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 @@ -809,8 +822,7 @@ func permitNdp(session uintptr, baseObjects *baseObjects, weight uint8) error { 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])) + setFilterConditions(&filter, definition.conditions) err := fwpmFilterAdd0(session, &filter, 0, &filterID) if err != nil { @@ -895,8 +907,51 @@ func permitHyperV(session uintptr, baseObjects *baseObjects, weight uint8) error return nil } -// Block all traffic except what is explicitly permitted by other rules. -func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { +// Block all traffic on restritced routes except what is explicitly permitted by other rules. +func blockRoutes(routes []netip.Prefix, session uintptr, baseObjects *baseObjects, weight uint8) error { + allOnesV4 := netip.AddrFrom4([4]byte{0xff, 0xff, 0xff, 0xff}) + storedPointersV4 := make([]*wtFwpV4AddrAndMask, 0, len(routes)) + denyConditionsV4 := make([]wtFwpmFilterCondition0, 0, len(routes)) + for _, a := range routes { + if !a.Addr().Is4() { + continue + } + address := wtFwpV4AddrAndMask{ + addr: binary.BigEndian.Uint32(a.Addr().AsSlice()), + mask: binary.BigEndian.Uint32(netip.PrefixFrom(allOnesV4, a.Bits()).Masked().Addr().AsSlice()), + } + denyConditionsV4 = append(denyConditionsV4, wtFwpmFilterCondition0{ + fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS, + matchType: cFWP_MATCH_EQUAL, + conditionValue: wtFwpConditionValue0{ + _type: cFWP_V4_ADDR_MASK, + value: uintptr(unsafe.Pointer(&address)), + }, + }) + storedPointersV4 = append(storedPointersV4, &address) + } + + storedPointersV6 := make([]*wtFwpV6AddrAndMask, 0, len(routes)) + denyConditionsV6 := make([]wtFwpmFilterCondition0, 0, len(routes)) + for _, a := range routes { + if !a.Addr().Is6() { + continue + } + address := wtFwpV6AddrAndMask{ + addr: a.Addr().As16(), + prefixLength: uint8(a.Bits()), + } + denyConditionsV6 = append(denyConditionsV6, wtFwpmFilterCondition0{ + fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS, + matchType: cFWP_MATCH_EQUAL, + conditionValue: wtFwpConditionValue0{ + _type: cFWP_V6_ADDR_MASK, + value: uintptr(unsafe.Pointer(&address)), + }, + }) + storedPointersV6 = append(storedPointersV6, &address) + } + filter := wtFwpmFilter0{ providerKey: &baseObjects.provider, subLayerKey: baseObjects.filters, @@ -907,12 +962,13 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { } filterID := uint64(0) + setFilterConditions(&filter, denyConditionsV4) // // #1 Block outbound traffic on IPv4. // { - displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv4)", "") + displayData, err := createWtFwpmDisplayData0("Block restricted routes outbound (IPv4)", "") if err != nil { return wrapErr(err) } @@ -930,7 +986,7 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { // #2 Block inbound traffic on IPv4. // { - displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv4)", "") + displayData, err := createWtFwpmDisplayData0("Block restricted routes inbound (IPv4)", "") if err != nil { return wrapErr(err) } @@ -944,11 +1000,13 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { } } + setFilterConditions(&filter, denyConditionsV6) + // // #3 Block outbound traffic on IPv6. // { - displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv6)", "") + displayData, err := createWtFwpmDisplayData0("Block restricted routes outbound (IPv6)", "") if err != nil { return wrapErr(err) } @@ -966,7 +1024,7 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { // #4 Block inbound traffic on IPv6. // { - displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv6)", "") + displayData, err := createWtFwpmDisplayData0("Block restricted routes inbound (IPv6)", "") if err != nil { return wrapErr(err) } @@ -980,6 +1038,9 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error { } } + runtime.KeepAlive(storedPointersV4) + runtime.KeepAlive(storedPointersV6) + return nil } @@ -1018,15 +1079,14 @@ func blockDNS(except []netip.Addr, session uintptr, baseObjects *baseObjects, we } filter := wtFwpmFilter0{ - providerKey: &baseObjects.provider, - subLayerKey: baseObjects.filters, - weight: filterWeight(weightDeny), - numFilterConditions: uint32(len(denyConditions)), - filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&denyConditions[0])), + providerKey: &baseObjects.provider, + subLayerKey: baseObjects.filters, + weight: filterWeight(weightDeny), action: wtFwpmAction0{ _type: cFWP_ACTION_BLOCK, }, } + setFilterConditions(&filter, denyConditions) filterID := uint64(0) @@ -1138,15 +1198,14 @@ func blockDNS(except []netip.Addr, session uintptr, baseObjects *baseObjects, we } filter = wtFwpmFilter0{ - providerKey: &baseObjects.provider, - subLayerKey: baseObjects.filters, - weight: filterWeight(weightAllow), - numFilterConditions: uint32(len(allowConditionsV4)), - filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&allowConditionsV4[0])), + providerKey: &baseObjects.provider, + subLayerKey: baseObjects.filters, + weight: filterWeight(weightAllow), action: wtFwpmAction0{ _type: cFWP_ACTION_PERMIT, }, } + setFilterConditions(&filter, allowConditionsV4) filterID = uint64(0) @@ -1186,8 +1245,7 @@ func blockDNS(except []netip.Addr, session uintptr, baseObjects *baseObjects, we } } - filter.filterCondition = (*wtFwpmFilterCondition0)(unsafe.Pointer(&allowConditionsV6[0])) - filter.numFilterConditions = uint32(len(allowConditionsV6)) + setFilterConditions(&filter, allowConditionsV6) // // #7 Allow IPv6 outbound DNS. |