How do I create RAW TCP/IP packets in C++?

2020-02-17 07:07发布

问题:

I'm a beginning C++ programmer / network admin, but I figure I can learn how to do this if someone points me in the right direction. Most of the tutorials are demonstrated using old code that no longer works for some reason.

Since I'm on Linux, all I need is an explanation on how to write raw Berkeley sockets. Can someone give me a quick run down?

回答1:

Start by reading Beej's guide on socket programming . It will bring you up to speed on how to start writing network code. After that you should be able to pick up more and more information from reading the man pages.

Most of it will consist of reading the documentation for your favourite library, and a basic understanding of man pages.



回答2:

For starters, it would be helpful if you clarify what you mean by "raw". Traditionally this means that you want to craft all of the layer 4 header (TCP/UDP/ICMP... header), and perhaps some of the IP header on your own. For this you will need more than beej's tutorial which has been mentioned my many here already. In this case you want raw IP sockets obtained using the SOCK_RAW argument in your call to socket (see http://mixter.void.ru/rawip.html for some basics).

If what you really want is just to be able to establish a TCP connection to some remote host such as port 80 on stackoverflow.com, then you probably don't need "raw" sockets and beej's guide will serve you well.

For an authoritative reference on the subject, you should really pick up Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition) by Stevens et al.



回答3:

For TCP client side:

Use gethostbyname to lookup dns name to IP, it will return a hostent structure. Let's call this returned value host.

hostent *host = gethostbyname(HOSTNAME_CSTR);

Fill the socket address structure:

sockaddr_in sock;
sock.sin_family = AF_INET;
sock.sin_port = htons(REMOTE_PORT);
sock.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;

Create a socket and call connect:

s = socket(AF_INET, SOCK_STREAM, 0); 
connect(s, (struct sockaddr *)&sock, sizeof(sock))

For TCP server side:

Setup a socket

Bind your address to that socket using bind.

Start listening on that socket with listen

Call accept to get a connected client. <-- at this point you spawn a new thread to handle the connection while you make another call to accept to get the next connected client.

General communication:

Use send and recv to read and write between the client and server.

Source code example of BSD sockets:

You can find some good example code of this at wikipedia.

Further reading:

I highly recommend this book and this online tutorial:

4:



回答4:

A good place to start would be to use Asio which is a great cross-platform (incl Linux) library for network communication.



回答5:

You do this the exact same way you would in regular C, there is no C++ specific way to do this in the standard library.

The tutorial I used for learning this was http://beej.us/guide/bgnet/. It was the best tutorial I found after looking around, it gave clear examples and good explanations of all functions it describes.



回答6:

I've been developing libtins for the past year. It's a high level C++ packet crafting and sniffing library.

Unless you want to reinvent the wheel and implement every protocol's internals, I'd recommend you to use some higher level library which already does that for you.



回答7:

There are tons of references on this (of course, Stevens' book comes to mind), but I found the Beej guide to be incredibly useful for getting started. It's meaty enough that you can understand what's really happening, but it's simple enough that it doesn't take you several days to write a 'hello world' udp client/server.



回答8:

Poster, please clarify your question.

Almost all responses seem to think you're asking for a sockets tutorial; I read your question to mean you need to create a raw socket capable of sending arbitrary IP packets. As I said in my previous answer, some OSes restrict the use of raw sockets.

http://linux.die.net/man/7/raw "Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets."



回答9:

Read Unix Network Programming by Richard Stevens. It's a must. It explains how it all works, gives you code, and even gives you helper methods. You might want to check out some of his other books. Advanced Programming In The Unix Enviernment is a must for lower level programming in Unix is general. I don't even do stuff on the Unix stack anymore, and the stuf from these books still helps how I code.



回答10:

Libpcap will let you craft complete packets (layer2 through layer 7) and send them out over the wire. As fun as that sounds, there's some caveats with it. You need to create all the appropriate headers and do all the checksumming yourself. Libnet can help with that, though.

If you want to get out of the C++ programming pool, there is scapy for python. It makes it trivial to craft and transmit TCP/IP packets.



回答11:

easy:

#include <sys/socket.h>
#include <sys/types.h>

int socket(int protocolFamily, int Type, int Protocol)
// returns a socket descriptor

int bind(int socketDescriptor, struct sockaddr* localAddress, unsigned int addressLength)
// returns 0 

...etc.

it's all in sys/socket.h