I'm trying to spec out the foundations for a server application who's purpose will be to..
1 'receive' tcp and/or udp packets
2 interpret the contents (i.e. header values)
To add more detail, this server will receive 'sip invites' and respond with a '302 redirect'.
I have experience with Net::Pcap and perl, and know I could achieve this by looping for filtered packets, decoding and then using something like Net::SIP to respond.
However, there's a lot of bloat in both of these modules/applications I don't need. The server will be under heavy load, and if I run TCPDUMP on it's own, it loses packets in the kernel due to server load, so worry it wont be appropriate :(
Should I be able to achieve the same thing by 'listening' on a socket (using IO::Socket for example) and decoding a packet?
Unfortunatly by debugging, it's hard to tell if IO::Socket will give me the opportunity to see a raw packet? And instead it automatically decodes the message to a readable format!
tl;dr: I want to capture lots of SIP Invites, analyse the head values, and respond with a SIP 302 redirect. Is there a better way than using tcpdump (via Net::Pcap) to achieve this?
Thanks,
Moose
Is there a better way than using tcpdump (via Net::Pcap) to achieve this?
Yes. Using libpcap (that's what you meant instead of tcpdump in that question) is a bad way to implement a TCP-based service, as you will have to reimplement much of TCP yourself (libpcap gives you raw network-layer packets), and the packets your program gets will also get delivered to the Internet protocol stack on your machine, so:
if there's nothing on your machine listening on the TCP port to which the other machines are trying to connect, the connection requests will get a RST from the TCP code and think the connection attempt failed;
if there is something on your machine listening on that port, it'll probably accept the connection, and it and your program will both try to communicate with the other machine, which will probably confuse its TCP stack and cause various bad and random things to happen.
It's not much better for UDP:
if there's nothing on your machine listening on the UDP port to which the other machines are trying to connect, the connection requests will probably get an ICMP Port Unreachable message from the UDP code, which may make it think the connection attempt failed;
if there is something on your machine listening on that port, it'll probably accept the connection, and it and your program will both try to communicate with the other machine, which will probably confuse its SIP stack and cause various bad and random things to happen.
IO:Socket will probably not give you raw packets, and that's a good thing; you won't have to implement your own IP and TCP/UDP stack. If your goal is to implement a redirect server on your machine, you have no need to receive raw packets; you want to receive SIP INVITEs with all the lower-level processing done for you by your machine's IP/TCP/UDP stack.
If you already have a SIP implementation on your machine, and you want to act as a "firewall" for it, so that, for some INVITEs, you send back a 302 redirect and prevent the SIP implementation on your machine from ever seeing the INVITEs in question, you will need to use the same mechanism that your particular OS uses to implement firewalls. There is no libpcap-like wrapper for those mechanisms, as far as I know.
Related
I am trying to establish a TCP/IP connection between a controller (client) and a program in my PC (server) using C++, I used a sniffer to see how client’s requests are being sent and I found out that each connect request from the controller is sent from a different port and known IP, it starts with random port number and increment by 1 with each request till I restart the controller or the server receives the request, I have some questions.
1- Is that a standard behaviour and what is the idea behind this knowing that the controller is a Mitsubishi controller?
2- Is there any way I can get the new port of the controller without using accept?
This is not so much the behaviour of the controller as it is the network stack running on top of the controller and may be integrated into the controller hardware (Search keyword: TCP offload).
This is expected behaviour. To prevent all sorts of nasty side effects, a simple example is late packets from a previous connection trying to sneak in as legitimate packets for a later connection, a port is not recycled for reuse for a lengthy period after the socket using the port is closed. Your port may not be available for use. A simple solution is to do exactly what OP's network stack did: sequentially assign the next port number.
Not with BSD-style sockets. accept accepts a connection with the client. If you do not accept, you don't get a socket to handle the connection and with the socket, you should not care what the port is. It's all abstracted away and hidden out of sight.
If this is a problem, consider using a connectionless protocol like UDP. You don't get automatic re-transmission when packet loss is detected and all of the other nice things TCP does for you, but there is no connection overhead.
I am trying to implement a program that is able to send TCP packets alone by itself. Ideally I want to send a packet to a port in a computer and have it processed. This means that I am trying to do it without having a client/server files pair.
However, I am finding it really hard to do this as anywhere I look there is mention of both the client and the server files. And if I try to run the client file or the server files by themselves, it doesn't even work as they depend on each other.
Is it possible to do what I want?
Not sure why you want to do that. But in order to send such packets, you need to use API for IP raw socket (SOCK_RAW), instead of TCP.
So you can send IP packets with payload of your "crafted TCP".
I want an http message to be sent and processed quickly by a remote server, via an already established persistent TCP connection
How can I optimize the communication?
I have a few ideas, but I am not knowledgeable enough about networking to know if they make sense:
HTTP sits on top of TCP. But how does it work exactly? Specifically, if I send 1 http message, does it translate into only 1 tcp message? (I know the initial handshake takes 3 round trip time, but I do not care about this, as the connection is already established). I guess it depends on the Maximum Segment Size that the server can accept?
Can I ask the server for a bigger maximum segment size if needed? How can I do it (I use python, httplib and socket modules, it would be ideal in this language).
The remote server works with TCP, but could I try sending it UDP messages? I know UDP is faster, but could this idea work?
I'll allow myself to comment/answer in-text:
I have a few ideas, but I am not knowledgeable enough about networking
to know if they make sense:
Exactly! Read up on TCP and HTTP, on wikipedia, for a starter. It will make things much easier to discuss. Probably also faster than asking on stackoverflow ;)
HTTP sits on top of TCP. But how does it work exactly?
Well, exactly like protocols work over each other in a layered protocol stack. Read Wikipedia's TCP article, and about the OSI/ISO layer model.
Specifically, if I send 1 http message, does it translate into only 1
tcp message?
No. HTTP itself doesn't care (and it doesn't have to) into how many lower level packets communication gets split.
(I know the initial handshake takes 3 round trip time,
but I do not care about this, as the connection is already
established).
3 time? That's not something that makes sense. Read about the TCP handshake and how HTTP asks for a document.
I guess it depends on the Maximum Segment Size that the
server can accept?
Among a lot of different other factors; really: HTTP doesn't care the least!
Can I ask the server for a bigger maximum segment size if needed?
No. Your network stack will most probably automatically use the biggest MTU that works.
How can I do it (I use python, httplib and socket modules, it would be
ideal in this language).
The remote server works with TCP, but could I try sending it UDP messages?
There are some specialized HTTP-over-UDP protocols, but they are not HTTP. Generally, HTTP is spoken over TCP, but again, the internet works on a layered protocol stack, and higher level protocols usually don't care what transports their data -- you could perfectly well have an HTTP session over carrier pidgeons!
I know UDP is faster, but could this idea work?
It's not. That's a misconception. UDP doesn't have automatic re-requesting for packets that got lost along the way, which, for things like multimedia or games might make sense, but using TCP gives you an ordered session, which is necessary for HTTP.
I have no experience with sockets nor multiplayer programming.
I need to code a multiplayer mode for a game I made in c++. It's a puzzle game but the game mode will not be turn-based, it's more like cooperative.
I decided to use UDP, so I've read some tutorials, and all the samples I find decribes how to create a client that sends data and a server that receives it.
My game will be played by two players, and both will send and receive data to/from the other.
Do I need to code a client and a server?
Should I use the same socket to send and receive?
Should I send and receive data in the same port?
Thanks, I'm kind of lost.
Read how the masters did it:
http://www.bluesnews.com/abrash/chap70.shtml
Read the code:
git clone git://quake.git.sourceforge.net/gitroot/quake/quake
Open one UDP socket and use sendto and recvfrom. The following file contains the functions for the network client.
quake/libs/net/nc/net_udp.c
UDP_OpenSocket calls socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)
NET_SendPacket calls sendto
NET_GetPacket calls recvfrom
Do I need to code a client and a server?
It depends. For a two player game, with both computers on the same LAN, or both on the open Internet, you could simply have the two computers send packets to each other directly.
On the other hand, if you want your game to work across the Internet, when one or both players are behind a NAT and/or firewall, then you have the problem that the NAT and/or firewall will probably filter out the other player's incoming UDP packets, unless the local player goes to the trouble of setting up port-forwarding in their firewall... something that many users are not willing (or able) to do. In that case, you might be better off running a public server that both clients can connect to, which forwards data from one client to another. (You might also consider using TCP instead of UDP in that case, at least as a fallback, since TCP streams are in general likely to have fewer issues with firewalls than UDP packets)
Should I use the same socket to send and receive?
Should I send and receive data in the same port?
You don't have to, but you might as well -- there's no downside to using just a single socket and a single port, and it will simplify your code a bit.
Note that this answer is all about using UDP sockets. If you change your mind to use TCP sockets, it will almost all be irrelevant.
Do I need to code a client and a server?
Since you've chosen to to use UDP (a fair choice if your data isn't really important and benefits more from lower latency than reliable communication), you don't have much of a choice here: a "server" is a piece of code for receiving packets from the network, and your "client" is for sending packets into the network. UDP doesn't provide any mechanism for the server to communicate to the client (unlike TCP which establishes a 2 way socket). In this case, if you want to have two way communication between your two hosts, they'll each need server and client code.
Now, you could choose to use UDP broadcasts, where both clients listen and send on the broadcast address (usually 192.168.1.255 for home networks, but it can be anything and is configurable). This is slightly more complex to code for, but it would eliminate the need for client/server configuration and may be seen as more plug 'n play for your users. However, note that this will not work over the Internet.
Alternatively, you can create a hybrid method where hosts are discovered by broadcasting and listening for broadcasts, but then once the hosts are chosen you use host to host unicast sockets. You could provide fallback to manually specify network settings (remote host/port for each) so that it can work over the Internet.
Finally, you could provide a true "server" role that all clients connect to. The server would then know which clients connected to it and would in turn try to connect back to them. This is a server at a higher level, not at the socket level. Both hosts still need to have packet sending (client) and receiving (server) code.
Should I use the same socket to send and receive?
Well, since you're using UDP, you don't really have a choice. UDP doesn't establish any kind of persistent connection that they can communicate back and forth over. See the above point for more details.
Should I send and receive data in the same port?
In light of the above question, your question may be better phrased "should each host listen on the same port?". I think that would certainly make your coding easier, but it doesn't have to. If you don't and you opt for the 3rd option of the first point, you'll need a "connect back to me on this port" datafield in the "client's" first message to the server.
I am using the Winsock API (not CAsyncSocket) to make a socket that listens for incoming connections.
When somebody tries to connect, how can I get their IP address BEFORE accepting the connection? I am trying to make it only accept connections from certain IP addresses.
Thanks
SO_CONDITIONAL_ACCEPT socket option. Here
Also, pretty sure it's available in XP and Server 2003, not just Vista.
Two reasons why I do not want to accept the connection in order to check the remote IP address:
1). The client would see that there is a listening socket on this port. If i decide to reject the client connection, I would not want them to know that there is a socket listening on this port.
2). This technique is not as efficient and requires more CPU, RAM, and network usage; so it is not good in case of a Denial Of Service attack.
When using ATM, the CONNECT ACK packet will come from the most recent switch, not the end client. So, you would have to call accept() on the socket, then look at the address (based on the passed addr_family), and at that point just close the socket. By the time it reaches the requester, it will probably just get a failure.
And I'm not sure how many resources you think this will take up, but accepting a connection is at a very low level, and will not really be an issue. It's pretty easy to drop them.
If you come under a DoS attack, your code CAN quit listening for a preset amount of time, so the attacker just gets failures, if you are so worried about it.
Does it really matter if the client knows there is a socket listening? Try using telnet to connect to your localhost on port 137 and see how fast the file sharing in windows drops the connection... (If you even have it enabled, and if I remembered the correct port number.. heh..)
But, at the SOCKET level, you are not going to be able to do what you want. You are talking about getting down to the TCP level, and looking at the incoming connection requests, and deal with them there.
This can be done, but you are talking about a Kernel driver to do it. I'm not sure you can do this in user-mode at all.
If you want Kernel help with this, let me know. I may be able to give you some examples, or guidance.
Just my own two cents, and IMVHO...
accept the connection, look at the IP, if it is not allowed, close the connection
Edit:
I'm assuming you're talking about TCP connection. When you listen to the port and a connection comes from a client, the API will perform the TCP 3-way handshake, and the client will know that this port is being listened to.
I am not sure if there is a way to prevent sending any packets (i.e. accepting the connection) so that you can look at the IP address first and then decide.
The only way I can think of is to do packet filtering based on the source IP at the network layer (using firewall, for example).