Asterisk keeps confusing public and private IPs so calls have no audio when softphones are behind NAT - asterisk

I'm trying to set up a voip system using asterisk and custom made mobile apps to make calls between users.
The system works perfectly when set up on the same network, but once deployed on the online server due to the fact that Softphones are behind NAT, audio is not going through but all SIP packets are properly received and softphones ring but when a call is open, no audio is heard on both endpoints.
I've looked everywhere about how to set up asterisk to work with endpoints behind NAT, but everything online talks about sip on the older versions of Asterisk. But i'm using the latest version of Asterisk which is using Pjsip.conf, i've tried different settings for the endpoints but RTP still confuses the IPs and tries to route the RTP packets to the private IP instead of the public IP.
I've tried rewrite_contact, direct_media, force_rport, ice_support, rtp_symmetric with different options, don't seem to find the perfect setting.
Has anyone done this before? do you have any documentation that i can look at for the latest versions of Asterisk?

Apparently it's not anything that needs to be done on the asterisk deployment. It was a client issue, the client sip phone needs to have RPORT for media enabled and I was using MizuDroid which did not have that feature. Once I switched to Zoiper and set that option on, everything started working properly.

In your transport of pjsip (type=transport used by your extensions) you have to set local_net, external_media_address, external_signaling_address :
[transport-udp-nat]
type = transport
protocol = udp
bind = 0.0.0.0
local_net = (your local network like 192.168.0.0/24)
external_media_address = (your external IP)
external_signaling_address = (your external IP)
Also, you have to use in your extensions:
rewrite_contact = yes
direct_media = no
force_rport = yes
rtp_symmetric = yes

Related

Is it possible to restrict ForceBindIP to only inbound/outbound traffic?

I'm using ForcebindIP to point an app at a specific network adapter, like this:
forcebindip -i 192.168.0.5 MyCSharpApp.exe
This works fine and the app isn't aware (or doesn't access) any of the other network adapters on the PC.
Is it possible to restrict ForceBindIP to outbound traffic only leaving the app to receive data from any local network adapter? Or even to specify a network adapter for outbound and another for inbound traffic?
I can't find an extra startup parameter for ForceBindIP that does this.
I'd appreciate any help with this.
If I get your problem correctly, you want to bind your application to listen for packets on all available interfaces but return packets to only through one given interface. I also assume it's a server application and you don't have neiter source code nor control over its behaviour.
Disclosure: I do not know how ForceBindIP works internally, I'm basing my understanding of it on this passage from the website:
it will then inject a DLL (BindIP.dll) which loads WS2_32.DLL into memory and intercepts the bind(), connect(), sendto(), WSAConnect() and WSASendTo() functions, redirecting them to code in the DLL which verifies which interface they will be bound to and if not the one specified, (re)binds the socket
Problems to overcome
I don't believe your desired configuration is possible with just one application level DLL injector. I'll list a few issues that ForceBindIP will have to overcome to make it work:
to listen to a socket, application has to bind() it to a unique protocol-address-port combination first. An application can bind itself to either a specific address or a wildcard (i.e. listen on all interfaces). Apparently, one can bind to wildcard and specific address simultaneously as outlined in this SO question. This however will be two different sockets from the application standpoint. Therefore your application will have to know how to handle this sort of traffic.
When accepting client connection, accept() will create a new socket and parameters on that are managed by Windows, I don't believe there's an API to intercept binding here - by this time the connection is considered established.
Now imagine, we somehow got a magic socket. We can receive packets on one interface and send to another. The client (and all routing equipment on the way) will have to be aware that two packets originating from two different source IP addresses are actually part of the same connection and be able to assemble the TCP session (or correctly merge UDP streams).
You can have multiple gefault gateways with different priorities and rules (which is a whole different topic to explore) but as far as I'm aware that's not going to solve your particular issue: majority of routing protocols assume links are symmetric and expect packets to keep within same interface. There are special cases like asymmetric routing and network interface teaming but they have to be implemented on per-interface level.
One potential solution
One way to achieve what you're after (I don't know enough about your environment to claim it will work), will be to create a virtual interface, set it into yet another IP network, bind your application to it, then use firewall (to, say, allow multicast backets into the "virtual" network) and routing from that network to required default gateway with metric set to 1. I also suspect just any Windows will not be that flexible, so you might need like a Server Edition.
I am sorry this didn't turn out to be the ready-to-fly solution, I however am hoping this gives you more context to the problem you are facing and points you into other directions to explore.
You can use Set-NetAdapterAdvancedProperty command in Powershell to set the flow control of your specified adapter
To get the names and properties of all the network adapter :-
Get-NetAdapterAdvancedProperty -Name "*"
Suppose you want the network adapter named "Ethernet 2" to be only used to receive data from internet then type :-
Set-NetAdapterAdvancedProperty -Name "Ethernet 2" -DisplayName "Flow Control" -DisplayValue "Rx Enabled"
You can find more in :
https://learn.microsoft.com/en-us/powershell/module/netadapter/set-netadapteradvancedproperty?view=win10-ps
Microsoft winsock example has a usage in their example for limiting a socket to only send or receive mode. It might help.
https://learn.microsoft.com/en-us/windows/win32/winsock/complete-client-code
Outbount and Inbount limits are not imposed while binding. But latter or when connection is established.
Line of code pertaining to this in client code is toward the end.
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);

Reply with unsupported protocol when writing custom network stack

I have been writing my own version of the 802.11 protocol with network stack. This is mostly a learning experience to see more in depth on how networks work.
My question is, is there a standard for replying to client devices that a certain protocol is unsupported?
I have an android device connecting to my custom wifi device and immediately sending a TON of requests at the DNS port of my UDP protocol. Since I would like to test out other protocols I would very much like a way for my wifi device to tell the android device that DNS is not available and get it to quite down a little.
Thanks in advance!
I don't see a possibility to send a reply that a service is not available.
I can't find anything about this case in the UDP specification.
One part of the DNS specification assumes that there are multiple DNS servers and defines how to handle communication with them. This explains part of the behavior in your network, but does not provide much information how to handle it.
4.2.1 Messages - format - UDP usage
The optimal UDP retransmission policy will vary with performance of the
Internet and the needs of the client, but the following are recommended:
The client should try other servers and server addresses
before repeating a query to a specific address of a server.
The retransmission interval should be based on prior
statistics if possible. Too aggressive retransmission can
easily slow responses for the community at large. Depending
on how well connected the client is to its expected servers,
the minimum retransmission interval should be 2-5 seconds.
7.2 Resolver Implementation - sending the queries
If a resolver gets a server error or other bizarre response
from a name server, it should remove it from SLIST, and may
wish to schedule an immediate transmission to the next
candidate server address.
According to this you could try to send garbage back to the client, but this is rather a hack, or an error, but how does an error look like? Such a solution assumes that you have knowledge about the service that you don't support.
I believe that the DNS - requests can be avoided by using DHCP. DHCP allows to specify DNS-servers as listed in the linked page. This is the usual way that I know for a DNS-resolver in a LAN to get initial DNS servers although I don't find anything about this in the DNS specification. You can give the Android - device a DNS-server with DHCP so that it does to need to try to query your device. Querying your device could be a fallback.
Additionally to DNS there is mDNS which uses multicasts in the network to send queries. This seems not to be the protocol you have to do with because it uses the special port 5353.
Not possible to stop DNS in the way you intend. However, only for your tests you can check the UDP messages and find out the names the device is looking for. Then you update the hosts file (google how to do it: http://www.howtogeek.com/140576/how-to-edit-the-hosts-file-on-android-and-block-web-sites/) and add those names with some localoop IP address. That might work for your test.
Other possibility is to change DNS server to some localloop IP address: http://xslab.com/2013/08/how-to-change-dns-settings-on-android/
Again, this is only to avoid having all the DNS messages through the wifi connection.

Mininet with ONOS: ARP works fine, Ping wont start

I build a custom mininet topology: 2 hosts with 2 switches between them:
Host1====Switch1====Switch2====Host2
After filling the flowtables with ONOS, the setup works fine. But I have trouble with handling packets that are forwarded to the SDN-Controller.
As controller I use my own onos-app.
I tried some pinging and sniffed the interfaces with tcpdump.
When one host pings the other host, the host sends an arp request. This request reaches the other host and it replies. Even the reply reaches correct the ping-host. But then... Nothing happens.
I would expect the first host to send the ping after he had received the correct arp reply. But instead it does absolutely nothing.
This even doesn't work using only one switch.
Why does the ping itself doesn't start?
Have you any idea what I did wrong?
Thank you.
R you using ONOS or RYU? It seems like you are using RYU.
If you are RYU: Do you have controller setup properly. Run the RYU using the provided controller code like simple_switch_13.py. See if that works.
If you are ONOS, have you installed features? Based on this tutorial you shuld install a feature. something like:
onos> feature:install onos-app-fwd
I don't know how you are programming the switches but for both controllers note that you should add flows for both directions.
Also, sometimes the flows have a very short lifetime that by the time packets arrive they are expired.
If none of these helped, could you provide more details.
OK. Problem solved :-D
This is what went wrong:
The onos-core itself places the default rules for ARP, IPv4 and IPv6, that redirect packets to the controller. Even if the onos-core writes such a default rule to the flowtable of the switch , it doesnt mean that all packets reach your app. In my case only the ARP-packets reached my app, not the IPv4-packets. Therefor I must add 3 lines to the "#Activate"-section of my app.
#Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.ifwd");
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
//***ADD THESE 3 LINES*********************************************************
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
//*****************************************************************************
}

How do VoIP calls get through a firewall

I installed an Obi100 (VoIP device with RJ11 to connect normal phones) behind my router, which has UPNP disabled and no ports forwarded. Somehow, it still receives VoIP calls and I am confused how that works.
I was getting a bunch of spam phone calls that weren't even going through my voip provider, so I think they were able to send the calls directly to my Obi100. I fixed that with a special filter rule in the Obi100, but I don't even see how someone could contact the Obi100 from outside anyway.
I believe the Obi devices use Google TCP based APIs to send/receive calls instead of SIP which is what many would assume when they hear VoIP. You were probably receiving inbound calls to your google account once they see you are "online" when your obi device connects with google. The setting probably disables announcing your availability.

Nat punch, MasterServer/Server/Client. Client can't talk to Server on known public ip and port

I have 3 applications: a MasterServer, a Server and a Client.
The MasterServer is running on: 70.105.155.5:15555 (port forwarded with UPnP)
I create a server and let the MasterServer know I exist. The MasterServer keeps my public ip and port. The port that the MS gets is randomly assigned by my router (lets say: 70.105.155.5:16666). The server keeps messaging the MasterServer each 10sec to keep that same port open.
I open up the client, on which it asks the MasterServer for the public ip and port of a server. The MasterServer returns: 70.105.155.5:16666. I know 100% sure that the server's public port 16666 is still open because I can check that in my logs.
But all messages sent from Client => Server are never received. At the same time the Server is still getting messages from MasterServer through 16666.
So this is really puzzling. Am I forgetting something? Is my understanding of NAT punch flawed?
Thanks for any help!
There are multiple issues here, and it depends on the router's security configuration too, often in ways the user cannot control. The general excuse is that it's a security precaution, but really firewalling and NAT are two separate concerns. Anyway, most home users are stuck with whatever they've got. They do usually have the option to explicitly map a port, and UPnP can help you too if the router supports it.
But going back to NAT, to begin with you're likely to have a problem if your server and client are sitting behind the same NAT, which seems to be the case given the addresses you quoted above. Most NATs only rewrite incoming packets from the public interface - so packets that physically arrive on the private interface, even if they're addressed to the public IP, won't be forwarded. To support this configuration in the wild you need the devices to advertise their private addresses to the MasterServer, and detect when they want to talk to other devices behind the same NAT, and if so, use the private address rather than going through the NAT. This is flawed in many ways, especially with nested NATs, but I think it's the best you can do.
Beyond that, in the more common case where all the devices are behind different NATs, some routers will only allow incoming traffic on a forwarding port if it's from the place they originally sent the outgoing traffic to (which resulted in the port opening up in the first place). Some also require it to come from the same source port on the remote device.
The workaround is for the MasterServer to do a bit more work. The gist is that it should tell both peers to send a packet to each other; these may or may not get through, but simply sending the packet out through the Server's NAT to the Client's public IP address may be enough to get the Server's NAT to correctly forward later packets from the Client. And vice versa.
In practice it is even more complicated, because the Server's NAT may use a different port when talking to Client to what it used when talking to MasterServer. So while this may open up a port for the Client to talk back to the Server, but it might not be the one the Client is expecting to use. If the NAT behaves like this, then you need to look at how predictable its choice of port numbering is. Some just increase one by one (but bear in mind there may be other devices behind the same NAT causing the number to jump more than one step at a time). For these ones, the Client needs to spam a range of Server ports to try to figure out which one got opened up. Again the MasterServer is in the best position to coordinate this.
Others seem totally random in port allocations, and there's not much you can do with those. But it's only terminal if both ends are behind these random NATs. So long as one end is more amenable to being opened up, the random end won't matter.
Also note that some NATs use a different outgoing port for each port on the target - this also makes prediction a lot harder, even in the case that the ports are not randomly assigned. Again, so long as one end of the connection is flexible, you can tolerate these NATs but in a peer-to-peer context they will be a nightmare in the end because they just can't talk to each other.

Resources