使用 macOS 网络扩展将传出 TCP 流量过滤到特定 IP

问题描述

我正在使用网络扩展来过滤到特定 IP 的传出 TCP 流量:

import NetworkExtension
import os.log


class FilterDataProvider: NEFilterDataProvider {

    override func startFilter(completionHandler: @escaping (Error?) -> Void) {

        let endpoint = NWHostEndpoint(hostname: "111.111.111.111",port: "0")
        let networkRule = NENetworkRule(remoteNetwork: endpoint,remotePrefix: 0,localNetwork: nil,localPrefix: 0,protocol: .TCP,direction: .outbound)
        let filterRule = NEFilterRule(networkRule: networkRule,action: .filterData)

        // Allow all flows that do not match the filter rules.
        let filterSettings = NEFilterSettings(rules: [filterRule],defaultAction: .allow)

        apply(filterSettings) { error in
            if let applyError = error {
                os_log("Failed to apply filter settings: %@",applyError.localizedDescription)
            }
            completionHandler(error)
        }
    }
    
    override func stopFilter(with reason: NEProviderStopReason,completionHandler: @escaping () -> Void) {

        completionHandler()
    }
    
    override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict {

        guard let socketFlow = flow as? NEFilterSocketFlow,let remoteEndpoint = socketFlow.remoteEndpoint as? NWHostEndpoint,let localEndpoint = socketFlow.localEndpoint as? NWHostEndpoint else {
                return .allow()
        }

        os_log("Got a new flow with local endpoint %{public}@,remote endpoint %{public}@,direction %{public}@",localEndpoint,remoteEndpoint,flow.direction == .inbound ? "inbound" : "outbound")

        return .allow()
    }
}

但是,我也收到了我不感兴趣的 IP 的回调:

2021-06-02 06:58:53.333438-0700 0x1bf8     Default     0x0                  666    0    com.mycompany.MyApp: Got a new flow with local endpoint 0.0.0.0:0,remote endpoint 111.111.111.111:80,direction outbound
2021-06-02 06:59:27.487968-0700 0x1d11     Default     0x0                  666    0    com.mycompany.MyApp: Got a new flow with local endpoint 0.0.0.0:0,remote endpoint 111.222.111.222:80,direction outbound
2021-06-02 07:00:06.118907-0700 0x1d74     Default     0x0                  666    0    com.mycompany.MyApp: Got a new flow with local endpoint 0.0.0.0:0,remote endpoint 123.123.123.123:80,direction outbound

此外,当我尝试不仅拦截 TCP 流量而且拦截 UDP 时,在 NENetworkRule 构造函数中提供“.all”而不是“.TCP”时,我开始从许多不同的 IP 接收出站和入站流量。

我做错了什么?谢谢。

解决方法

定义您希望允许的规则。比,为所有不符合此规则的流量选择 defaultAction = NEFilterACtionFilterData

NSMutableArray<NEFilterRule *>* rs = [NSMutableArray arayWithCapacity:1];

NEFilterRule*r=[[NEFilterRule alloc] initWithNetworkRule:[[NENetworkRule alloc] 
initiWithDestinationNetwork:[NWHostEndpoint endpointWithHostname:@"111.111.111.111" port:@"0"] 
                     prefix:0 
                   protocol:NENetworkRuleProtocolTCP 
                                                 action:NEFilterActionAllow];

[rs addObject:r];

NEFIlterSettings* s = [[NEFilterSettings alloc] initWithRules:rs defaultAction:NEFilterACtionFilterData];

// 'self' is the packet filter provider implementation of yours
[self applySettings:s completionHandler^(NSError * e) { ... }

,

至少我解决了一个问题。 “remotePrefix”具有子网掩码的含义。提供它的值为 0 是错误的。要仅捕获我感兴趣的 IP,需要将其设置为 32。描述为 here