UPnP: Auto-Updating or Removing old port mappings - networking

Does a UPnP portmapping update automatically when the local computers IP updates dynamically? If not then how will you remove the old port mapping if you now have a new IP and will not be "authorised" to do so.
Suppose I could forward right before and remove right after I need the connection to be made. My issue is; what if the computer shuts down mid connection and turns back on with a different IP? Surely something must've been made in order to circumvent this.

Found an answer
UPnP is soft-state.
In [1], section 4.1, PortMappingLeaseDuration is described as a state variable that describes that a mapping is only leased for a certain duration. (indeed soft state) also [1], section 5.10, describes that if your router is set up as DHCP it must delete any IGD state for that IP if it changes
[1] https://www.rfc-editor.org/rfc/rfc6970

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);

How to recycle(or flush) an IPV6 node's global address by RA(router advertisement)?

I'm developing on linux router to assign global IP for node linked. The node I am testing on is a Windows PC.
I managed to assign global IP by sending Router Advertisement as per rfc4861.
+---------+---------------+----------+
07:14:07,632,019 ETHER
|0 |33|33|00|00|00|01|ce|74|19|9a|07|a2|86|dd|60|00|00|00|00|38|3a|ff|fe|80|00|00|00|00|00|00|cc|74|19|ff|fe|94|01|9c|ff|02|00|00|00|00|00|00|00|00|00|00|00|00|00|01|86|00|a1|25|40|40|ff|ff|00|00|00|00|00|00|00|00|03|04|40|c0|ff|ff|ff|ff|ff|ff|ff|ff|00|00|00|00|fc|01|ab|ab|cd|cd|ef|e0|00|00|00|00|00|00|00|00|05|01|00|00|00|00|05|dc|
After sending this RA from router (link-local addr fe80::cc74:19ff:fe94:19c), the tested PC can be auto-configured with global addr fc01:abab:cdcd:efe0:e1fb:2297:51db:af84 and fc01:abab:cdcd:efe0:29e9:52fd:2527:dbca.
Above is background.
But how can I recycle(or flush) the global IP on the tested PC? I have tried sending RA with (M=0,O=0,Router Lifetime=0), to my understanding to rfc4861, but this doesn't work. After that still I can see the global IP assigned, checking by cmd ipconfig.
RFC4862 could answer this question:
A RA with short "preferred lifetime" (like 1s) could deprecate the old IPv6 address, but which still may count as valid address. Back to current question, the address is not easy to be flushed by short "valid lifetime" because the consideration of avoiding DOS attack.
If someone who does need to flush the old IP, please refer to RFC4862 5.5.3:
If RemainingLifetime is less than or equal to 2 hours, ignore the Prefix Information option with regards to the valid lifetime, unless the Router Advertisement from which this option was obtained has been authenticated (e.g., via Secure Neighbor Discovery [RFC3971]). If the Router Advertisement was authenticated, the valid lifetime of the corresponding address should be set to the Valid Lifetime in the received option.

Is it possible to build an arp request packet in such a way that will cause a router to forward it over subnets?

What I'm trying to do is get all the ip addresses in my network, and I thought, assuming I know the address of all subnets could use arp requests to achieve that if there was a way to forward these requests over different subnets.
For example , assume I had two hosts
192.168.0.2/24 and 192.168.1.2/24
connected via router using IP addresses 192.168.0.1/16 192.168.1.1/16.
I would like to send an arp request from 192.168.0.2/16 to 192.168.1.2/16.
I thought maybe if the arp request was encapsulated in layer 3 header containing 192.168.1.2/24, or 192.168.1.255/24 as the dsetination this will work.
If it is possible and you know a tool that does that I will be happy to know about this tool.
If it isn't, I would like to know what happens to a packet like the one I described above
I would like to know what happens to a packet like the one I described above
If you encapsulate some info into standard IP-packet, then, naturally, it will be routed to the IP-destination host. Yet if the remote host knew nothing about this non-standard packet, then nothing would happen.
If you really want to get something out of this, you need to have up and running some software server on that remote host, which is able to process your requests. That is, you need some Proxy ARP: either existing implementation, or made of your own.
If you don't have such "an agent" in the target subnetwork, then you're out of luck. Go with sequential IP-scanning until be banned by admin.

Asterisk + NAT. Either get called or be called

My Asterisk set up is as follows:
- I have 2 grandstream GXP 2000 phones connected to my router
- My small linux server (with asterisk) is connected to the router as well
I have a dynamic ip from my isp provider, but I signed up for DynDNS
When I started I could call people and talk to them. If people rang me, the phone would ring, and I could hear them speak. They could not hear me. I found out this was because of the directmedia / canreinvite setting. So I set this to:
canreinvite=no
directmedia=no
Now, people could call me and I could answer. However, due to this change I can call people, but as soon as they answer, I can't hear them, I only hear static. When I remove the two lines I add, everything is back as it was before.
What could be the issue ? The 5060 port is forwarded to my server ,as well as the 1000 - 2000 udp rang.
Regards,
Digits
First of all, you should probably read the sip.conf.sample file delivered with Asterisk. Specifically, read the NAT SUPPORT section. canreinvite and directmedia (which are the same setting by the way) attempt to set up the RTP streams directly between the UAs involved in a call, bypassing Asterisk. Thus, while that setting is affected by NAT, it does not necessarily control the channel driver behavior with respect to NAT - so its not surprising you're still having issues.
Without knowing whether or not the UAs in question are sending rport, its difficult to know for sure what your settings should be. That being said, based on your problem description, you may want to set the 'nat' parameter in your [general] section to either:
nat = force_rport,comedia
; or, depending your version
nat = yes
Note that you can set nat on a peer by peer basis, but that's discouraged for security reasons.
Additionally, you may also need to explore the extern* settings, such as externhost.
Ok, some information for other people in the same situation:
- check your codecs, make sure you get no errors in the Asterisk CLI (command line interface). I got errors, but it worked, so I didn't care. That was a mistake
- upgrade to asterisk 1.8
- set directmedia = no
- it's upd range 10000 to 20000 (I missed a 0).
This all fixed this problem.

Determining when to try an IPv6 connection and when to use IPv4

I'm working on a network client program that connects to public servers, specified by the user. If the user gives me a hostname to connect to that has both IPv4 and IPv6 addresses (commonly, a DNS name with both A and AAAA records), I'm not sure how I should decide which address I should connect to.
The problem is that it's quite common for machines to support both IPv4 and IPv6, but only to have global connectivity over IPv4. The most common case of this is when only IPv6 link-local addresses are configured. At the moment the best alternatives I can come up with are:
Try the IPv6 address(es) first - if the connection fails, try the IPv4 address(es); or
Just let the user specify it as a config setting ("prefer_ipv6" versus "prefer_ipv4").
The problem I can see with option 1 is that the connection might not fail straight away - it might take quite a while to time out.
Please do try IPv6. In the significant majority of installations, trying to create an IPv6 connection will fail right away if it can't succeed for some reason:
if the system doesn't support IPv6 sockets, creating the socket will fail
if the system does support IPv6, and has link-local addresses configured, there won't be any routing table entry for the global IPv6 addresses. Again, the local kernel will report failure without sending any packets.
if the system does have a global IP address, but some link necessary for routing is missing, the source should be getting an ICMPv6 error message, indicating that the destination cannot be reached; likewise if the destination has an IPv6 address, but the service isn't listening on it.
There are of course cases where things can break, e.g. if a global (or tunnel) address is configured, and something falsely filters out ICMPv6 error messages. You shouldn't worry about this case - it may be just as well that IPv4 connectivity is somehow broken.
Of course, it's debatable whether you really need to try the IPv6 addresses first - you might just as well try them second. In general, you should try addresses in the order in which they are returned from getaddrinfo. Today, systems support configuration options that let administators decide in what order addresses should be returned from getaddrinfo.
Subsequent to the question being asked the IETF has proposed an answer to this question with RFC6555, a.k.a. Happy Eyeballs.
The pertinent point being the client and server may both have IPv4 and IPv6 but a hop in between may not so it is impossible to reliably predict which path will work.
You should let the system-wide configuration decide thanks to getaddrinfo(). Just like Java does. Asking every single application to try to cater for every single possible IPv6 (mis)configuration is really not scalable! In case of a misconfiguration it is much more intuitive to the user if all or none applications break.
On the other hand you want to try to log annoying delays and time-outs profusely, so users can quickly identify what to blame. Just like every other delays ideally, including (very common) DNS time-outs.
This talk has the solution. To summarize;
Sometimes there are problems with either DNS lookups or the subsequent connection to the resolved address
You don't want to wait for connecting to an IPv6 address to timeout before connecting to the IPv4 address, or vice versa
You don't want to wait for a lookup for an AAAA record to timeout before looking for an A record or vice versa
You don't want to stall while waiting for both AAAA and A records before attempting to connect with whichever record you get back first.
The solution is to lookup AAAA and A records simultaneously and independently, and to connect independently to the resolved addresses. Use whatever connection succeeds first.
The easiest way to do this is to allow the networking API do it for you using connect-by-name networking APIs. For example, in Java:
InetSocketAddress socketAddress = new InetSocketAddress("www.example.com", 80);
SocketChannel channel = SocketChannel.open(socketAddress);
channel.write(buffer);
The slide notes say at this point:
Here we make an opaque object called an InetSocketAddress from a host
and port, and then when we open that SocketChannel, that can complete
under the covers, doing whatever is necessary, without the
application ever seeing an IP address.
Windows also has connect-by-name APIs. I don’t have code fragments for
those here.
Now, I’m not saying that all implementations of these APIs necessarily
do the right thing today, but if applications are using these APIs,
then the implementations can be improved over time.
The di!erence with getaddrinfo() and similar APIs is that they
fundamentally can’t be improved over time. The API definition is that
they return you a full list of addresses, so they have to wait until
they have that full list to give you. There’s no way getaddrinfo can
return you a partial list and then later give you some more.
Some ideas:
Allow the user to specify the preference on a per-site basis.
Try IPv4 first.
Attempt IPv6 in parallel upon the first connection.
On subsequent connections, use IPv6 if the connection was successful previously.
I say to try IPv4 first because that is the protocol which is better established and tested.

Resources