Reply with unsupported protocol when writing custom network stack - networking

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.

Related

Will mobile device network switch affect http communication?

For mobile Apps, it is a valid assumption that the network may be intermittent, or it may switch from one to another as the user keeps moving. For example, your device is connected to a startbucks wifi and you are using the App before you grab your coffee and walk out of the store -> Your mobile device network may switch from wifi to carrier network, 3G/4G/LTE. Even with the carrier network itself, it may switch among 3G/4G/LTE depending on their coverage at your position.
Question,
Will this intermittent network, or frequently network switch affect the http communication?
For example, an http request was sent out with Wifi, and while the server is processing the request, the device already switched to 4G. Will the device still be able to receive the response?
If Yes, how is Http or TCP designed to support this scenario?
If No, should we try to solve the problem from the application layer? and How?
Will the device still be able to receive the response?
For current practice, No. After network is switched:
Device's public IP address is changed.
TCP connection is based on IP protocol, so all current TCP connection would be destroyed.
HTTP is based on TCP connection, so it would be destroyed too.
Actually, you can make a simple experiment to verify this: Put a web page on internet and make the web server delay the page delivery for 30 seconds. Visit this page and switch network while waiting for the response.
However, this is a classic problem in mobile world, so some work is doing to give mobile device a constant IP, which will keep TCP&HTTP alive when device switches from one network to another. You can check Mobile IP in wikipedia for more information on various technologies and protocols.
If No, should we try to solve the problem from the application layer?
It depends on whether you can tolerate network interruption for your application. If it is a static web page, I think it is totally OK to leave this problem alone, and wait for Mobile IP technology improvement in future. If it is a highly network-dependent application, such as online video or stock market app, I think this problem should be solved in application layer.
and How?
There are 3 methods to fix/workaround this problem (maybe more):
Cache. Prefetch resources, so that when TCP connection is destroyed and reconnected, device can use cached resources. This works well in online audio/video apps, but it does not apply when no resource can be prefetched (realtime stock market data for example).
Take TCP re-connection as first priority. Check your code, when HTTP failed due to destroyed TCP connection, re-send HTTP request as early as possible.
Improve user experience when network interruption do happens.

Under which conditions and how does Webrtc PeerConnection work without a TURN server?

Reading about Webrtc i get the feeling that "it will drop server bandwidth usage dramatically" except for "a few corner enterprise-firewall cases" where one needs a TURN server which relays the whole traffic between the peers.
For example, altough not webrtc related but the idea is similar, the wikipedia article of Chatroulette states: The website uses Adobe Flash to display video and access the user's webcam. Flash's peer-to-peer network capabilities (via RTMFP) allow almost all video and audio streams to travel directly between user computers, without using server bandwidth. However, certain combinations of routers will not allow UDP traffic to flow between them, and then it is necessary to fall back to RTMP.
Also similar articles on Webrtc focus on "yeah there might be problems with firewalls so you need a TURN server but ignore this and look at my awesome PeerConnection javascript code".
What i don't understand:
A Connection between two peers requires a server socket to be open so the peers can connect to it. Even UDP requires the concept of a udp server socket. Since nearly all not-server internet connected peers are behind some kind of router. E.g. every smartphone uses a wifi router, desktop PC's use the router of the service provider, ...
It shouldnt be possible to connect to a server socket hosted on a smartphone (browser webrtc server socket) or desktop cause of the router/firewall.
Thus my understanding is practically no two peers which need to send their traffic through the internet will be able to use a direct P2P connection, right?
So the only useful case to use Webrtc is in a LAN like environment, right?
Furtherly in case of a video chat service like chatroulette based on webrtc would need to use a bunch of TURN servers to relay nearly ALL traffic. Which makes Webrtc equally costly regarding server bandwidth like hosting my own solution.
So my question is: Am i right? If not what is the technical detail that allows a PeerConnection to be used without a TURN server but for two nodes separated by the Internet? How is the connection established on Layer 4 the TCP/UDP Transport Layer? Is it using UDP and all wifi routers allow hosting UDP server sockets or such? Which wouldnt make much sense cause of NAT and security.
UPDATE 1:
Digging a bit further i found what "symmetric nat" means and what it has to do with enterprises: In most enterprises it seems that the device connected to the internet has symmetric nat implemented. This means that the routing table which maps internal "internal-ip:internal-port" tuples to "internet-ip:internet-port" also stores "destination-ip:destination-port". So such routes/nats store a table for every (tcp?) connection having 6 columns "internal-ip:internal-port:internet-ip:internet-port:destination-ip:destination-port". This means no one else but the destination is allowed to communicate with internal-ip:internal-port.
Whereas non-enterprise-routers seem to only store the "internal-ip:internal-port:internet-ip:internet-port" combination. Thats also what is meant as "poke a hole in the firewall".
You're not right. All peers have IP addresses in order to communicate, and can be reached on those same addresses, provided a firewall allows it.
NATs tend to be optimized for client-initiated client-server traffic only. That typically means they initially allow outbound traffic only, and only allow inbound traffic on the same line after outbound traffic has happened. Perfect for servers. See this WebRTCHacks article for an intro to the problem.
This is where ICE comes in to attempt to poke holes in the firewall from the inside (client-side), in order to establish a line of communication directly between two peers, without needing any "server" socket, whatever that means.
How ICE works is quite complicated, and is explained in detail in the RFC.
But in broad terms it works in a number of steps:
Each peer (e.g. browser) has an "ICE agent" that collects candidates. Candidates are addresses (IP:port numbers) at which this peer can be reached, including:
Host candidates: e.g. immediate LAN/wifi/VPN IPs of the machine.
Server-reflexive candidates: public (outside-NAT) addresses of the machine, obtained by bouncing requests off mirroring (STUN) servers on the internet.
Relay candidates: addresses to a shared TURN server to forward data if all else fails.
Once discovered, candidates are inserted into the local SDP, and trickled over the signaling channel to the other peer, where they are inserted in it's remote description, where the other agent sees them.
Once an ICE agent has both local and remote candidates, it starts pairing local and remote candidates, and checks them for connectivity by sending STUN requests on them (effectively attempts at reaching the peer).
Successful pairs are ones both ICE agents have gotten a response back on (a 4-way handshake if you will).
If there's more than one successful pair, they're sorted by some metric, and the best pair becomes selected.
The selected pair is then used to send media over. One pair is needed for each track of (video or audio) media.
If a better pair is found later, the selected pair may change, affecting what address media is sent on.
TURN should only be needed in cases either where both clients are behind symmetrical NATs, or UDP traffic is blocked entirely.

What is a SNMP ping?

I know what SNMP is and I know what ping is. What is meant by a 'SNMP ping'? SNMP can be used to see if devices on a network are still alive.. what does it use to do this? I wouldn't have thought an SNMP ping is the same as an ICMP ping?
As you correctly suspected SNMP "ping" is definitely not the same as ICMP ping. What it does is to try to retrieve some basic information through SNMP like DNS name, system name, location, system type, system description etc. and if successful the "ping" is deemed to be successful too.
But this is not any kind of standard the way ICMP Ping (echo) is. There is no special "ping" command in SNMP - it's just a name for a tool used to scan whether SNMP is alive at some target device (by retrieving some common MIB values). So as you would expect the implementation differs too as a consequence of it being a useful tool rather than a standard.
But that has little effect in practice as there is a set of 'mandatory' SNMP records so if a device does not respond to those, you can be pretty sure it doesn't run SNMP. For an SNMP "ping" to work SNMP MUST be enabled on the target device of course ... which isn't the case by default most of the time in general so that's a big difference to ICMP Ping which can be used almost universally.
I hope I answered your question
Ping was "Packetized Internet Node Groper", originally a tool that implemented an ICMP echo response. "Ping" is now commonly used to convey an abstraction of checking whether a device is online, available, responding.
There are MIB options to ask a device to ping or trace route something -- which seem to be asking a device to ICMP to a third party and indicate success/failure -- but the colloquial use of "snmp ping" is to check responsiveness by asking a simple SNMP question of a static data point and get a response.
Most devices offer some response to requests in the 1.3.6.1.2 subtree, but it's not a hard/fast requirement. For example, on a Unix (-like) command line, one may try "snmpget -v 1 -c public 192.168.0.1 1.3.6.1.2.1.1.1.0" to ask "192.168.0.1" what its name is. The device may respond; it typically will not NAK if the access (version 1, community string "public", in this case) is incorrect. The switch(es) in between may choose to alert the requestor "unreachable", but may not. In this case as others, if there is no response, the messages or hints aside from "no response" may be helpful.
It is typical for an SNMP ping to be equivalent to an ICMP echo. IBM states, for example, that it issues a single ICMP echo (to the SNMPD on the receiving end) and returns the minRTT. If a response times out, then it sends another raw echo packet after 1 second, and another again after 2 seconds. If there is yet no reponse, -1 is returned.
Cisco also has a sort of similar implementation (SNMP GET/SET/PING-MIB). It is definitely implementation-specific, however.
Source
"ping" is just a generic term for sending a message for the purpose of seeing whether you get back a response.
ICMP is the most common method of "pinging" a host on an IP network. If you get an ICMP echo response from an IP address, then you know that something out there is able and willing to receive and reply to at least some network traffic for that address. Receiving a reply to an ICMP ping does not tell you anything about the state of any other network services. Not receiving a reply does not tell you anything at all: there are dozens of reasons why you might not receive a response to an ICMP ping at any particular moment.
The concept of a "ping" applies to any mechanism of communication. Some network protocols have specific standards for performing a "ping". For most, "pinging" just means trying to perform some basic operation to see if it works. For example, you could "ping" an HTTP server by just connecting to port 80 and doing "HEAD / HTTP/1.0". If you get back an HTTP response, then you know there's an HTTP server operational. The same idea applies to SNMP or any another network application.
In most contexts I have heard 'SNMP Ping' used, it was referring to a DISMAN PING. This method allows you to use SNMP to control a device or host remotely and tell it to 'ping' another device. Typically, this would be a traditional ICMP ping.
For example, imagine you are on your laptop, and you have a webserver which seems to be taking a long time to load a page. You can't quickly tell if it is a problem with the network between you and the webserver, the network between the webserver and the database, or something with one of the servers themselves. You want to eliminate network first, so you first ping the webserver from your laptop. No loss, and the latency looks reasonable. You ping the database server from your laptop, and it looks good too. The problem with the laptop-database ping test is it doesn't tell you what is going on between the webserver and the database. Ideally, you'd log into the webserver and ping the database, but you don't have a shell account. You do, however, have a read/write SNMP access. So, you decide to use 'snmpset' from your laptop to the webserver to create a table (for ping results) and specify a target (database server) to ping. The webserver snmpd initiates an ICMP ping from the webserver to the database and stores the results in a table. You then do a 'snmpget' from the laptop to pull the webserver-database ping results.
The other contexts you might see 'snmp ping' may be simply a snmpget from a SNMP client to a SNMP daemon to confirm SNMP is working.
In my understanding, an SNMP ping is the one defined in RFC 2925
https://www.rfc-editor.org/rfc/rfc2925
If the SNMP agent vendor indicates that a device supports this RFC, then you can use SNMP ping to monitor it. Otherwise, it won't work.
This is completely different from the "normal ping" (ICMP based).
Like ICMP ping, SNMP ping, just a form of a SNMP getrequest, is used to check the aliveness of any equipment that has standard SNMP agent running for monitoring. It is useful when the management systems that manage these equipments to query for the auto discovery. Any sysOid can be used to query the equipment as part of the request.

Constantly reading/writing data over a TCP/IP Port. Which one?

Unfortunately I don't know much networks. I am writing a program that has two versions. A server version and a client version. Lets assume that the client versions are installed on, say 20 PCs that are connected to the server over ethernet. The client versions needs to CONSTANTLY get some data from the server. The data is kind of serial. I wanted to know a way to broadcast the data that gets updated every second and make it available to all the other PCs in the network. Could I use the HTTP Port for this?, like writing the data to an HTML page or something? or Is there a better port or method for doing this?
Any ideas will be greatly appreciated.
This sounds like a pretty straightforward application of TCP sockets. The server would be set up to "listen" on a particular port (you pick the port number, say 12345), and each client would make a TCP connection to the server on that port.
Whenever the server has data to send, it would send it once to each connected client. This could mean that the server sends the data up to 20 times on different sockets, but that's fine. The client would read the data from its connected socket to the server.
There are other alternatives, such as UDP or even UDP multicast, but these usually end up being a lot more complicated because UDP doesn't guarantee that packets always arrive at the destination (and they may even be duplicated or out of order). TCP ensures that the data you send either arrives complete in the correct order, or doesn't arrive at all (in that case the connection would be dropped).
An example of this sort of multiple TCP connection is VNC:
VNC is widely used in educational contexts, for example to allow a distributed group of students simultaneously to view a computer screen being manipulated by an instructor, or to allow the instructor to take control of the students' computers to provide assistance.
There are many ways. you can choose any of them but i think, document below will help you a lot.
Multicast over TCP/IP HOWTO:
http://www.ibiblio.org/pub/Linux/docs/howto/other-formats/html_single/Multicast-HOWTO.html#sect-trans-prots

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