Hello.
We are facing a problem regarding the pausing and resuming of a network flow based on the application layer data.
Context
We are implementing an HTTP/HTTPS filtering feature. The main goals are:
- Analyze both HTTP and HTTPS protocols and allow or deny a flow based on the the exchanged data.
- Analyze not only Web-kit based applications but every HTTP/HTTPS traffic.
Implemented methods
In order to satisfy these requirements, and based on the SimpleFirewall sample, we have implemented these methods:
- handleNewFlow
- handleInboundData
- handleOutboundData
- handleInboundDataComplete and handleOutboundDataComplete (for cleaning purposes)
Application data processing
Firstly, we return “NEFilterNewFlowVerdict.filterDataVerdict(withFilterInbound: true, peekInboundBytes: Int.max, filterOutbound: true, peekOutboundBytes: Int.max)” to handleNewFlow in order to access the application layer data.
Afterwards handleInboundData and handleOutboundData parse the received HTTP/HTTPS data and returns one of these possible choices:
- “NEFilterDataVerdict.init(passBytes: passBytesCount, peekBytes: Int.max)” when we don’t have the required application layer data to perform the analysis.
- “NEFilterDataVerdict.pause()” whenever the information has been fulfilled and we can proceed with the analysis.
Finally, we perform a flowResume operation with the action resulting from the analysis, either "NEFilterNewFlowVerdict.allow()" or "NEFilterNewFlowVerdict.drop()".
Problem
The trouble is the flow is not correctly resumed. The paused data is not reinjected to the network and the connection does not progress.
Considerations
- Traffic interception is based on the SimpleFirewall Swift code, but application layer data parsing is written in C. We are using the bridging header and every data seems to be correct in both Swift and C sections.
- The analysis is performed in a separated thread inside the C code section. So we:
- Indicate Pause to the main thread that came from the Swift section, which in the end will return “NEFilterDataVerdict.pause()” to the system.
- Call Swift section from the analysis thread to perform a flowResume operation.
- As flowResume needs the NEFilterFlow object previously provided by handleNewFlow, we store a reference to it in an indexed flow cache inside the Swift section. That way the analysis thread will be able to obtain it.
- When the analysis thread calls Swift code we are not in the FilterDataProvider class context. This class has a method that performs the flowResume action. To call it we instantiate the class and call that method from the analysis thread context.
We would really appreciate it if you could bring some light to this issue. Thanks a lot, in advance.
Regards