Intercept IP address or Domain Name from safari using VPN - ios

Hello I am working on an application which can intercept the visited network traffic ip address list from iPhone (similar to Charles Proxy).
Currently I have written code to create a VPN profile using NETunnelProviderManager class.
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
guard let self = self else { return }
if self.manager != managers?.first {
self.manager = managers?.first
} else {
self.manager = self.makeManager()
}
self.manager?.saveToPreferences(completionHandler: { (error) in
if let error = error {
print("Error in saving VPN Config: \(error.localizedDescription)")
}
self.manager?.loadFromPreferences(completionHandler: { (error) in
if error == nil {
do {
try self.manager?.connection.startVPNTunnel()
} catch let vpnTunnelError {
print("Unable to start VPN Tunnel by error: \(vpnTunnelError.localizedDescription)")
}
} else {
print("Load From Preference Error")
}
})
})
}
}
private func makeManager() -> NETunnelProviderManager {
let manager = NETunnelProviderManager()
manager.localizedDescription = "NetworkTrafficVPN"
let proto = NETunnelProviderProtocol()
proto.providerBundleIdentifier = "com.NetworkTraffic.vpn-tunnel"
proto.serverAddress = "Network Traffic"
manager.protocolConfiguration = proto
let onDemandRule = NEOnDemandRuleConnect()
onDemandRule.interfaceTypeMatch = .any
manager.isOnDemandEnabled = true
manager.onDemandRules = [onDemandRule]
manager.isEnabled = true
return manager
}
Once I start the vpn tunnel (self.manager?.connection.startVPNTunnel()) from the created NETunnelProviderManager object
I get a callback in NEPacketTunnelProvider network extension method (startTunnel(options: [String : NSObject]?, completionHandler: #escaping (Error?) -> Void)).
I have created the NEPacketTunnelNetworkSettings inside startTunnel() method using the assigned IP address of the iPhone.
After calling the method self.setTunnelNetworkSettings(settings) { error in } I am getting network data callback inside
self.packetFlow.readPackets { (data, numbers) } method
class PacketTunnelProvider: NEPacketTunnelProvider {
// MARK: - Constants
let logger: Logger = Logger(subsystem: "NetworkTrafficSubsystem", category: "NetworkTrafficCategory")
let proxyServerPort: Int = 8888
let proxyServerAddress = "192.168.43.185" // Device assigned ip address
// MARK: - NEPacketTunnelProvider
override func startTunnel(options: [String : NSObject]?, completionHandler: #escaping (Error?) -> Void) {
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: proxyServerAddress)
settings.tunnelOverheadBytes = 80
settings.mtu = 1400
settings.ipv4Settings = NEIPv4Settings(addresses: [proxyServerAddress], subnetMasks: ["255.255.255.255"])
settings.ipv4Settings?.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings?.excludedRoutes = []
settings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
settings.dnsSettings?.matchDomains = []
self.setTunnelNetworkSettings(settings) { error in
if let e = error {
self.logger.info("Settings error")
completionHandler(e)
} else {
self.logger.info("Settings set without error")
self.readPacketObjects()
completionHandler(nil)
}
}
}
private func readPacketObjects() {
self.packetFlow.readPackets { (data, numbers) in
self.logger.info("Inside readPackets completionHandler")
// Way to print the ip address from the received data array
self.packetFlow.writePackets(data, withProtocols: numbers)
self.readPacketObjects()
}
}
}
But I am unable to decode the data object from self.packetFlow.readPackets { (data, numbers) in } method.
So my question is that in order to read the IP address of all the visited network traffic is this the correct approach or I need to do something else.
If this is correct approach then let me know how to decode the received Data object.
If not then please suggest the correct way to achieve this functionality.
Any help would be appreciated thanks.

Related

How to receive UDP Multicast and Unicast with Network Framework of iOS

I've been developing Smart House apps that require UDP communication of both Unicast and Multicast on iOS with Swift using CocoaAsyncSocket.
I'd like to use Network Framework instead of CocoaAsyncSocket.
I made a following trial program of receiving UDP at 3610 port with both Unicast and Multicast at "224.0.23.0".
With this program, I'm having a problem to receive both Multicast and Unicast.
This program can handle receiving Multicast, but not Unicast.
When I comment out "receiveMulticast()" in the init(), this program can handle receiving Unicast.
I need to handle receving both Multicast and Unicast at 3610 port.
Is there any advice?
=======================================
import Foundation
import Network
class Controller: ObservableObject {
#Published var rxContents = String()
#Published var rxFrom = String()
init() {
receiveMulticast()
receiveUnicast()
}
func receiveUnicast() {
guard let listener = try? NWListener(using: .udp, on: 3610)
else { fatalError() }
listener.newConnectionHandler = { (newConnection) in
print("connection OK")
newConnection.start(queue: .main)
self.receive(on: newConnection)
}
listener.stateUpdateHandler = { (newState) in
print("listener entered state \(String(describing: newState))")
}
listener.start(queue: .main)
}
func receiveMulticast() {
guard let multicast = try? NWMulticastGroup(for: [ .hostPort(host: "224.0.23.0", port: 3610) ], disableUnicast: false)
else { fatalError() }
let group = NWConnectionGroup(with: multicast, using: .udp)
group.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: true) { (message, content, isComplete) in
print("Received message from \(String(describing: message.remoteEndpoint))")
if let content = content, let message = String(data: content, encoding: .utf8) {
print("Received Message: \(message)")
}
}
group.stateUpdateHandler = { (newState) in
print("Group entered state \(String(describing: newState))")
}
group.start(queue: .main)
}
private func receive(on connection: NWConnection) {
connection.receiveMessage { (data: Data?, contentContext: NWConnection.ContentContext?, aBool: Bool, error: NWError?) in
self.rxFrom = String(describing: connection.endpoint)
print("Received message from \(self.rxFrom))")
print(data ?? "data is null")
if let data = data{
self.rxContents = String(format: "%#", data as CVarArg)
print("Received Message(unicast): \(self.rxContents)")
}
if let error = error {
print(error)
} else {
self.receive(on: connection)
}
}
}
}

openVPN Network extension packet tunnel provider not start to VPN tunnel

Open vpn not working properly. After configureVPN function start connection.startVpn part is run but nothing happened.But I would put in below
I also checked PacketTunnelProvider plist everthing seems perfect.
readFile function returns Data that receive from ovpn file.
Network extension entitlements also appended.
Any help would be great.
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
class ViewController: UIViewController {
var providerManager: NETunnelProviderManager!
override func viewDidLoad() {
super.viewDidLoad()
self.loadProviderManager {
self.configureVPN(serverAddress: "127.0.0.1", username: "uid", password: "pw123")
}
}
func loadProviderManager(completion:#escaping () -> Void) {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if error == nil {
self.providerManager = managers?.first ?? NETunnelProviderManager()
completion()
}
}
}
func configureVPN(serverAddress: String, username: String, password: String) {
guard let configData = self.readFile(path: "serverfile.ovpn") else { return }
print("configData\(configData)")
self.providerManager?.loadFromPreferences { error in
if error == nil {
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.username = username
tunnelProtocol.serverAddress = serverAddress
tunnelProtocol.providerBundleIdentifier = "com.bgnmobi.openDeneme.Packet" // bundle id of the network extension target
tunnelProtocol.providerConfiguration = ["ovpn": configData, "username": username, "password": password]
tunnelProtocol.disconnectOnSleep = false
self.providerManager.protocolConfiguration = tunnelProtocol
self.providerManager.localizedDescription = "GuardillaVPN" // the title of the VPN profile which will appear on Settings
self.providerManager.isEnabled = true
self.providerManager.saveToPreferences(completionHandler: { (error) in
if error == nil {
self.providerManager.loadFromPreferences(completionHandler: { (error) in
do {
print("aSDFs34dasdsadsa")
try self.providerManager.connection.startVPNTunnel() // starts the VPN tunnel.
} catch let error {
print(error.localizedDescription)
}
})
} else {
print("asdasdsadsa")
print(error)
}
})
}
}
}
func readFile(path: String) -> Data? {
let mypath = Bundle.main.path(forResource: "serverfile", ofType: ".ovpn")
if let dir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first{
let fileURL = dir.appendingPathComponent(mypath!)
//reading
do{
let text2 = try String(contentsOfFile: mypath!,encoding: String.Encoding.utf8)
print(text2)
let gerekliURL = URL(fileURLWithPath: mypath!)
print(gerekliURL)
return try Data(contentsOf: gerekliURL, options: .uncached)
}catch{
// print("can t read")
}
}
return nil
}
}
These parts would be match with your Target file. Be carefull in that point. That was a problem in my case and probably yours too.
private static let appGroup = "group.com.project.examplevpn"
private static let tunnelIdentifier = "com.project.examplevpn.Extension"

In iOS after session.startTunnel() connection status stops on connecting state

We are trying to connecting vpn (TCP & UDP) through “.ovpn” configuration using TunnelKit, But after calling startTunnel NEPacketTunnelProvider is not initiating.
Here's code:
private func makeProtocol() -> NETunnelProviderProtocol {
let credentials = OpenVPN.Credentials(textUsername.text!, textPassword.text!)
let configurationFileURL = Bundle.main.url(forResource: “xyz”, withExtension: "ovpn")
do {
let file = try OpenVPN.ConfigurationParser.parsed(fromURL: configurationFileURL!).configuration
var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: file)
builder.mtu = 1450
builder.shouldDebug = true
builder.masksPrivateData = false
let configuration = builder.build()
return try! configuration.generatedTunnelProtocol(
withBundleIdentifier: ViewController2.tunnelIdentifier,
appGroup: ViewController2.appGroup,
credentials: credentials
)
} catch {
print("Failed to send a message to the provider")
return NETunnelProviderProtocol()
}
}
func connect() {
configureVPN({ (manager) in
return self.makeProtocol()
}, completionHandler: { (error) in
if let error = error {
print("configure error: \(error)")
return
}
self.currentManager?.isEnabled = true
let session = self.currentManager?.connection as! NETunnelProviderSession
do {
try session.startTunnel()
print("start Tunnel called")
} catch let e {
print("error starting tunnel: \(e)")
}
})
}

Sending mails with SMTP Mailcore2 in Background while App is running

Im writing a iOS app which needs to send regular updates in the background after the user adds new data (Barcoder Scanner, scancodes). I can't find any ways to send the mail in background via SMTP and mailcore2 without problems and limitations.
I already tried this with:
Tried it with background fetch
https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/updating_your_app_with_background_app_refresh
But this is very irregular and it takes some time until it triggers.
In AppDelegate.swift:
func applicationDidEnterBackground(_ application: UIApplication) {
BackgroundTask.run(application: application) { [...] }
}
But then the data is only send if i close/minimize the app and if the BackgroundTask is not complete the app will freeze and I receive this error: XPC connection interrupted
I also run into problems because I need to wait for the sendOperation to return but as this is async I build a workaround to keep the Thread running and processing my "if success else ..." afterwards. More in the full code:
typealias CompletionHandler = (Error?) -> Void
/// Provides syncronous access to results returned by
/// asynchronous processes with completion handlers
class SyncMaker {
var result: Error? = nil
/// Generates a synchronous-compliant completion handler
func completion() -> CompletionHandler{
return {
(error: Error?) in
// Store result, return control
self.result = error
CFRunLoopStop(CFRunLoopGetCurrent())
}
}
// Perform task (that must use custom completion handler) and wait
func run(_ task: #escaping () -> Void) -> Error? {
task()
CFRunLoopRun()
return result
}
}
func applicationDidEnterBackground(_ application: UIApplication) {
BackgroundTask.run(application: application) { backgroundTask in
if (scanManager.hasDataToSend()) {
let smtpSession = MCOSMTPSession()
let settings: Settings = scanManager.getSettings()
smtpSession.hostname = settings.credMailServer
smtpSession.username = settings.credMailSource
print(settings.credMailSource)
smtpSession.password = settings.credMailPassword
smtpSession.port = UInt32(settings.credMailPort)
[…] Setting auth and connection typ
smtpSession.isCheckCertificateEnabled = false
smtpSession.timeout = 100
smtpSession.connectionLogger = {(connectionID, type, data) in
if data != nil {
if let string = NSString(data: data!, encoding: String.Encoding.utf8.rawValue){
NSLog("Connectionlogger: \(string)")
}
}
}
let builder = MCOMessageBuilder()
builder.header.to = [MCOAddress(displayName: settings.credMailDest, mailbox: settings.credMailDest)!]
builder.header.from = MCOAddress(displayName: settings.credMailSource, mailbox: settings.credMailSource)
builder.header.subject = "ScanLMS"
builder.htmlBody = ""
guard let attachment = MCOAttachment(data: scanManager.getSendData().data(using: .ascii), filename: "scans.txt") else {
print("Cant init attachment!")
backgroundTask.end()
return
}
attachment.mimeType = "text/plain"
builder.addAttachment(attachment)
let rfc822Data = builder.data()
let sendOperation = smtpSession.sendOperation(with: rfc822Data!)
var sendingError: Bool = true
print("Trying to send mail...")
if (sendOperation != nil) {
print("Starting sendOperation...")
let syncMaker = SyncMaker() //full class on top of code
let result = syncMaker.run {
sendOperation?.start(
syncMaker.completion())
}
if (result != nil) {
print("Error sending email: \(result!)")
} else {
sendingError = false
print("Successfully sent email!")
}
} else {
print("Cant init sendOperation")
sendingError = true
}
if (sendingError) {
print("Error, returning")
} else {
print("Send done")
print("Updating scanManager with send data...")
scanManager.updateSendData()
print("Done, returning")
}
} else {
print("No new send data")
}
backgroundTask.end()
}
}
I lowered the smtpSession.timeout = 100 to 3 (seconds) and now its not blocking the UI anymore. More a hack then a solution, but it works.

Socket.io Swift client handler doesn't trigger

I have issue with soket.io client, and as I read here, you should define socket manager as a global variable so it's not released by ARC.
My code with that in mind:
let manager = SocketManager(socketURL: URL(string: Api.SOCKET)!, config: [.log(true), .path(Api.SOCKET_PATH)])
let socket: SocketIOClient?
....
override func viewDidLoad() {
super.viewDidLoad()
subscribeOnTransaction() { }
}
func subscribeOnTransaction() {
if self.socket == nil {
socket = manager.socket(forNamespace: Api.SOCKET_PATH)
subscribeToChangesChannel { }
socket?.on(clientEvent: .connect) { data, ack in
self.socket?.emit("transaction", self.sellOrder.id!)
}
self.socket?.on(clientEvent: .statusChange) {data, ack in
print(data)
}
self.socket?.connect()
}
}
func subscribeToChangesChannel(completion: #escaping () -> Void) {
if let socket = self.socket {
socket.on("transaction/\(self.sellOrder.id!)") { data, ack in
print(data, ack)
if data.count > 0 {
let rawResult = data[0]
if let result = rawResult as? [String: Any] {
let newRawValue = result["new_val"]
if let transaction = self.parseSocketResponse(newRawValue) {
self.openTransactionTrackingScreen(transaction)
completion()
}
}
}
}
}
}
But it doesn't call the handlers when I set breakpoints. Connection is established, everything's fine, with log turned on I get
Got polling response
LOG SocketEnginePolling: Got poll message:
What might be the problem? Any ideas? Will appreciate any help, thanks

Resources