SimpleFirewall with objective-c

If I take the SimpleFirewall example provided by Apple, remove the SimpleFirewallExtension, add a new target that is also a NetworkExtension for content filtering, except where the language is objective-c, I have a weird problem. startFilter and stopFilter will be called correctly, but the packetHandler is never called.


I made sure the plist and entitlements are populated similarly as the swift example.


Why is that? What is different in objective-c for Network Extension?

Replies

Make sure in this case that you have the NEFilterProviderConfiguration's property for filterPackets set to true. If you look at the SimpleFirewall example in Swift you will the NEFilterProviderConfiguration being created in the ViewController. To call startFilter and stopFilter for a custom NEFilterPacketProvider make filterPackets is true and you have a class setup for NEFilterPacketProvider.


let providerConfiguration = NEFilterProviderConfiguration()

providerConfiguration.filterPackets = true

filterManager.providerConfiguration = providerConfiguration


Hope this helps.


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Unfortunately this didn't work. I think I'll just write the core of the extension in swift, and just use some bridges to import some C code I need.

You mentioned:

| I made sure the plist and entitlements are populated similarly as the swift example.


Did you also add the NEProviderClasses reference to activate your packet filter?


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Yes, I did. Inside the Info.plist for the extension, NEProviderClasses specified as a dict, with one element.


For swift, this element is:

com.apple.networkextension.filter-packet -> $(PRODUCT_MODULE_NAME).FilterPacketProvider


For objective-c, it is:


com.apple.networkextension.filter-packet ->FilterPacketProvider


(In both cases, FilterPacketProvider is indeed the name of the class I implement, that inherits from NEFilterPacketProvider).

I am also facing same issue. packetHandler is never called. Socket filter is working as expected. Issue is only with packet filter. And any idea how to inspect "packetBytes" payload? Like to which struct we can type cast it?

I am also facing same issue.

packetHandler
is never called.

My first step in debugging problems like this is to add a log point to my provider’s initialiser so that I can see whether the provider loaded at all.

And any idea how to inspect

packetBytes
payload? Like to which struct we can type cast it?

If things were that simple,

packetBytes
would be declared as a pointer to that struct. Rather,
packetBytes
points to the start of the packet. Packets are, in general, made up of a sequence of headers followed by an optional payload. The exact sequence of headers depends on the nature of the packet. In a packet filter, the first header is the link-layer header, which is based on the interface.

You typically parse a packet from the front. First up, you can use the interface to determine what sort of link-layer header to expect. The link-layer should include some a ‘protocol type’ value that tells you how to parse the next header.

For example, for an IPv4 packet carried over an Ethernet-like interface, the link-layer header will look like this:

  • destination MAC address, 6 bytes
  • source MAC address, 6 bytes
  • protocol, 2 bytes, 08 00

The value of 0x0800 in the protocol field tells you that the next header is the IP header.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Porvider's initializer and startFilter method also called. Issue is only with the PacketHandler closure (in Objective-C only)

The furthest I could go on this was to get both extensions initialized (their init was called). However, when I savedToPreference the filterManager to enable it, only the FilterDataProvider received the startFilter callback. The FilterPacketProvider did not receive it.

Have you been able to combine both a FilterDataProvider and a FilterPacketProvider in the same app, and to start both ?

I have done this in swift, where I can combine both providers (packet and data) under single extension. But in objective-c I couldn't.


If you are over installing your extension there could be a chance that latest changes would have not picked up. If so increment bundle version of the extension and try.

That's great to hear! I'll try again.


Here's what I tried but does not work:


- 1 system extension : MyDataAndPacketFilter.systemExtension

+ It's Info.plist contains this :


<dict>

<key>NEProviderClasses</key>

<dict>

<key>com.apple.networkextension.filter-data</key>

<string>$(PRODUCT_MODULE_NAME).FilterDataProvider</string>

<key>com.apple.networkextension.filter-packet</key>

<string>$(PRODUCT_MODULE_NAME).FilterPacketProvider</string>

</dict>

</dict>

</plist>



- 1 File FilterDataProvider.swift :


class FilterDataProvider: NEFilterDataProvider {
    override init() {
        super.init()
        os_log(" FilterDataProvider init")      
    }

    override func startFilter(completionHandler: @escaping (Error?) -> Void) {
        os_log("FilterDataProvider startFilter")
    }
  
    override func stopFilter(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        os_log("FilterDataProvider stopFilter")
        completionHandler()
    }
}


- 1 File FilterPacketProvider.swift :


class FilterPacketProvider: NEFilterPacketProvider {
    override init() {
        super.init()
        os_log("FilterPacketProvider init")
    }

    override func startFilter(completionHandler: @escaping (Error?) -> Void) {
        os_log("FilterPacketProvider startFilter")
        }
        completionHandler(nil)
    }
   
    override func stopFilter(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        os_log("FilterPacketProvider stopFilter")
        completionHandler()
    }
}


- In the main app (gui app), I do this:

+ load the 2 system extensions. This works fine

+ enable the filter via this :


func startFilter() {
        let filterManager = NEFilterManager.shared()
        loadFilterConfiguration { success in
            guard success else {
                os_log("Eror in startFilter")
                return
            }

           let providerConfiguration = NEFilterProviderConfiguration()
           providerConfiguration.filterPackets = true // 
           providerConfiguration.filterSockets = true // I set both to true
           
           filterManager.providerConfiguration = providerConfiguration
           filterManager.localizedDescription = appName           
            filterManager.isEnabled = true
           
            filterManager.saveToPreferences { saveError in
                DispatchQueue.main.async {
                    if let error = saveError {
                        os_log("Failed to save the filter configuration: %@", error.localizedDescription)
                        return
                    }
                }
            }
}


This does not work, as only 1 startFilter is called (the one of FilterDataProvider).


Can you tell what I am doing wrong?


Thanks!

load the 2 system extensions? Suppose to be one. Otherwise code looks ok to me.

"FilterPacketProvider init" got this log atlest?

1. Put breakpoint and check whether providerConfiguration.filterPackets hit.

2. Look for errors category in the output of log stream.

3. At last try this as well, systemextensionctl reset and restart.


Hope this helps you.

Yes, the 2 systems extensions are loaded correctly, I see the running proesses, and via systemextensionctl.


I see these messages in the console :


"FilterDataProvider init"

"FilterPacketProvider init"

"FilterDataProvider startFilter"


but I don't see


"FilterPacketProvider startFilter"


In the init of FilterPacketProvider, I print filterConfiguration.filterPacket and I verified indeed that it was set to True.


I tried to reset systemextensionctl and restart but it did not help.

No error messages? Crashes? If not include packetHandler closure and try. Looks like a weird behaviour.

In fact I don't see any advantage of having 2 extensions, You can have 1 extension with 2 providers.(which is working for me)

I agree with you, only 1 extension is better.


I tried with 1 or 2 extensions, but it didn't work.


I am not sure why, I'll continue to investigate.