NEPacketTunnelProvider packetFlow IP stack issue - ios

I have a custom VPN (with a custom protocol for receiving and sending packets) hosted on my local machine and running a Network Extension (NE for short) on my phone. All the configuration for the NE is set and the NE is running and logging to the console. The setup is as follows:
NE is reading packets from the packetFlow using packetFlow.readPacketsWithCompletionHandler
Packets are then sent to the VPN. I used two different methods for testing: the AsyncCocoaSocket library or the native NWTCPConnection to connect to the VPN.
I listen to responses from one options mentioned in 2 to receive the response packets.
Finally, I write the packets received back to the IP stack using packetFlow.write
I send the packets as I receive them in the AsyncCocoaSocket delegate methods or the NWTCPConnection read completion handler. The VPN responses sent match the ones received in the NE before writing them back into the stack.
The issue I'm having is that for example when I make a browser request the site doesn't render. It only works with very basic text-based test sites and single images. It only on the first request however not always guaranteed. It is very random and no packets seem to be dropped in the flow.
Summary:
Browser => Network extension read from packet flow => forward requests to VPN through tunnel => Listen for responses in Network Extension => write responses using packetFlow write => Browser
I'd expect the browser to render the site but it doesn't and neither do the apps making requests work.
Any guidance would be appreciated.
NOTE: This all works flawlessly when I connect using an Android device.

Related

Difference between App Proxy Provider and Packet Tunnel Provider

I'm reading the documentation of the App Proxy Provider and the Packet Tunnel Provider and am a bit puzzled.
The docs state that packet tunnel providers send and receive packets from/to the system, while app proxy providers send/receive flows to/from the system.
What's confusing from the packet tunnel provider documentation:
Packet tunnel providers can run in destination IP mode or source-application mode. The latter is one form of per-app VPN (the other form is an App Proxy Provider).
But in the NETunnelProvider class it says:
The default is NETunnelProviderRoutingMethodDestinationIP.
So by default, the Packet Tunnel Provider is actually an App Proxy Provider? What am I missing? Could someone explain their difference?
The AppProxy and PacketTunnel are options to implement VPN.
The AppProxy works with so called Flow objects, each flow is started by some application. AppProxy receives the flow and forward it to somewhere.
The PacketTunnel works with packets. It receives the packet and could do something with it (like, modify) before it goes to the network.
Now, the part of documentation may causing you troulbes relates to the question: what exeactly flows/packets do AppProxy and PacketTunnel receives?
AppProxy:
The NEAppProxyProvider class provides access to flows of network data
in the form of NEAppProxyFlow objects. Each NEAppProxyFlow object
corresponds to a socket opened by an app that matches the app rules
specified in the current App Proxy configuration.
That means, you will have all flows matches your rules go to your class method first, and then routed to some new address.
PacketTunnel:
Packet tunnel providers can run in destination IP mode or
source-application mode.
That mean, you can set the rule like "each packet that goes to "list of ip addresses", I want you to go through my class method and then into the tunnel" - and this will be destination IP mode.
Or you can set the rule like "all packets from app with bundle id com.my.app now go to my class method first and then into the tunnel" This is source-application mode.
This (the source application mode of PacketTunnelProvider) is one of per-app VPN forms, because it focused on the application, that produces traffic.
The AppProxy also focused on application that produces traffic, so it is the other form of per-app VPN, but it will give you the flow object app produces, not the packets with ip and tcp/udp headers.

Using Twilio to make/receive calls via Cisco SPA504G IP phone

Looking to place calls using our Cisco SPA504G IP phones through Twilio. We have 4 phone lines/numbers with Twilio and we want to use them to place and receive calls on physical phones.
Edited Question:
I found an interesting post in here: https://ertw.com/blog/2013/11/05/using-an-ip-phone-with-twilio/
This where my steps in order to get the phone to ring but I could not hear voice :/
I just bought: http://www.amazon.com/Grandstream-GXP1620-Medium-Business-Device/dp/B00VUU8EZM
Connected phone to my router. I am port forwarding all traffic in the ranges from 10000-20000 to the phone. I am also port forwarding port 5060 to the phone.
Uploaded the following xml file:
<Response>
<Say>Testing</Say>
<Dial>
<Sip>
sip:line1#24.51.221.98
</Sip>
</Dial>
</Response>
that can be found at: http://antnam.com/voip.xml
I called my internet provider and now I have a static IP address so that 24.51.221.98 never changes.
I configured my twilio number (855) 804-0420 to execute a GET # http://antnam.com/voip.xml
When I call (855) 804-0420 I can hear the phone that is connected to my router (voip phone) ring!!! So good news I am able to call the phone I purchased on step 1!
Once I answer the call I am not able to listen to voice :/ . What could I be doing wrong?
In summary everything works great I am just not able to listen to anything. It is as if the call is on mute. Am I missing to open more ports?
It sounds like this may just be a NAT traversal problem; if it is please move or remove this question, as this would only be relevant if you were programming this client. There is a ton of info out there about this issue (for example here is an excellent article that comes up as the first result when I google "voip nat traversal"), but here's a quick summary:
Why NAT causes a problem for VoIP
Most VoIP protocols use a data stream on one port (e.g. 5060 in this case) to negotiate connection information that includes among other things a socket (IP address and port) to receive audio/RTP traffic; there are 2 things about this negotiation of a socket that might be unexpected:
It can be any IP address and port combination, not just one that is on the VoIP device itself. So you might have for instance a VoIP server that negotiates a socket on another host that is not part of the SIP dialog, and which might be behind a NAT
The negotation is done at the OSI Application Layer (Layer 7), so it is normally untouched by the NAT process, which operates at Layers 3 and 4
How to diagnose missing audio due to NAT
If you're able to get packet captures (ideally on both WAN and LAN ports, so you can see your VoIP device's traffic before and after NAT), you can see the problem in action: just look for the packets containing SDP payloads (e.g. if you're doing SIP on UDP 5060, just filter for that port and you will see INVITE requests and 200 OK responses that contain SDP payloads); drill down to the c (Connection Information) and m (Media Description) lines, which should look something like the following:
c=IN IP4 192.168.1.114
m=audio 6094 RTP/AVP 0 8 101
If you're seeing something like this going out your WAN port, it means your VoIP device is requesting to be sent audio on 192.168.1.114:6094; the IP address is a private address and cannot be routed over the internet; the port is just one I picked randomly, but the one you see needs to be open and forwarded to your device
How to fix it
There are various solutions to this problem, which all come down to rewriting the private IP address that your device is giving out into the public one that your device's traffic is being NAT'd out on, so that when the remote device parses the Connection Information line in the SDP, it has a valid, publicly routable IP address to send the audio traffic to, and a UDP port that is NAT'd to your device. Sometimes the VoIP device itself can handle the rewriting (e.g. you can either statically tell the device in its configuration what its public IP is, or it can discover it from a protocol like STUN), sometimes the rewriting is done by the firewall/router that is doing the NAT (there are various names for this, like SIP ALG or SIP Fixup).
Unfortunately due to the variations in NAT implementations across various routers and firewalls, no solution can be guaranteed to work 100% of the time; and if you have multiple devices behind the same firewall, having it do the rewriting will only work for one of them.
In your case:
You mention 2 different VoIP devices, a Cisco SPA504G, and a Grandstream GXP1620. The datasheets for both devices say they support STUN, so I'd start looking in its config for the STUN settings or anything else that references NAT traversal. Also, make sure that the ports you are forwarding to the device are the ones that it uses, this is usually just another item in the config, called something like "RTP base port" or "RTP range"
I would also ensure that you nat transveral enabled with stun using a public stun server such as stun.sipgate.net
Note: STUN operates on TCP and UDP port 3478.
This is required as the phone needs to send the external ip in the sip packets. Without stun it will send the internal ip and the far end sip device will attempt to send the data there.

How do I send and receive network MIDI data in iOS?

How do I send and receive network MIDI data in iOS? I am able to resolve the server using bonjour and apply the service to a MIDI connection, but I don't know where to go from there. The documentation seems to be lacking, and there's not much information online.
Essentially, you need to connect to the session via Bonjour as you have done, and within your iOS app:
Create a client using MIDIClientCreate
Create an input port using MIDIInputPortCreate
This takes a pointer to a C function that will be called when MIDI data is received
You need to connect it to the MIDINetworkSession's defaultSession using MIDIPortConnectSource - connect it to the sourceEndpoint
Create an output port using MIDIOutputPortCreate
You can send data to the network session using MIDISend - send the packets to to the MIDINetworkSession defaultSession's destinationEndpoint
I wrote a few blog posts about this a while back, see here for source code etc.
Part 1
Part 2
Part 3

Best way to find is my custom ethernet device is online and what IP it has got for iOS?

Ideas:
1. Pinging all my subnet ( using simple ping etc )
2. Sending GET to all IP in my subnet? ( may be too slow) waiting for 200 or 404 reply.
Thanx
Can you program your ethernet device to respond to Bonjour (mDNS) requests? That's the preferred discovery mechanism in the OSX/iOS ecosystem. avahi is an open-source mDNS daemon you might be able to run if your device runs a UNIX-like OS. You might also be able to find or write an embeddable mDNS server that you could integrate into your server if you're not running an OS as such.
Otherwise, I'd probably go with a custom broadcast UDP packet that the device will respond to. (which is basically what Bonjour/mDNS does, but less general) To send a broadcast UDP packet, open a UDP (datagram) socket and send a packet to the local subnet's broadcast IP. Make the packet contents suitably unique, and get your device to respond, e.g. using an HMAC, to avoid picking up any other devices or daemons which coincidentally answer on the same port.
This is a pure IP networking question. What you want to do is to send a TCP/IP broadcast message to the network and have you custom device respond to it. See TCP/IP Guide for some basic details.

Socket Programming on BlackBerry

I am stuck creating a socket connection between blackberry client and java server. I need simple sample code which extends the socket API example from blackberry sample code.
We have a server that communicates with android systems and we need it to work with blackberry client as well.
Sorry for being late. And I am posting my comment here because of comment length. _screen.isDirectTCP() isn't an API method, so I am not sure what does this method return. But from the method name/signature I think this method is only used for checking whether Direct TCP connectivity is available or not on the device. Depending on the result, the application will append the connection parameter such as ";deviceside=....".
From the Network Transport article,
If you do not want your application to rely on the default connection
types described in the previous sections, explicitly state the
desired connection type by adding the “deviceside=” parameter to the
destination URL. If an application appends “;deviceside=true” to the
destination URL, then only a direct HTTP or TCP connection is
attempted. The application does not attempt to connect to the network
using the BlackBerry MDS. Alternatively, if an application appends
“;deviceside=false” to the destination URL, then the application only
attempts to connect to the network using the BlackBerry MDS. The
application does not attempt to connect to the network using a public
IP gateway.
Also please have a look at this link, What Is - Different ways to make an HTTP or socket connection.

Resources