Engineers use Alibaba Cloud to try to express different love

When you are young, love is like a TCP link. You can shake hands three times when you are in love, but when you break up, it is divided four times. And often long-lasting love is more like the icmp protocol, no matter where the other party is, whether it is a reliable connection or not, no matter when you ping her/him, she/he responds to you silently. This article is to talk about how to add a few lines of code to the kernel to let your goddess/male gods express your love when pinging you (the server). The effect is as follows (the left is the result of ping, you need to crack the ascii code to convert it into the corresponding character, and the right is the information directly read by using tcpdump to capture packets):

For the UNIX_LIKE system, if the sent content of ping is different from the received content, different parts will be displayed, then let your goddess or goddess slowly parse the ASCII code into what you want to tell her/him. Or tell her/him to use tcpdump to directly capture the private messages hidden in the ping. (For windows, I have not fully tested it, but I know that it will not directly display the difference between the request message and the echo message like the unix_like system, so everyone needs to capture the packet and extract the information carefully)

1. ICMP protocol These you need to know:

Those who have studied computer networks must know that the encapsulation of a network packet is mainly composed of multiple packet headers and user data belonging to different network protocol layers: link layer packet header + network layer IP packet header + transport layer packet Header + carried content + frame trailer. The ICMP packets are located in the following positions in the entire Ethernet frame:

The figure above shows an unfragmented ICMP packet or the first IP fragment of a longer ICMP packet (the fragmented packet will not have an ICMP header). RFC792 (
11 ICMP message types are defined in, which are distinguished by the 8bit "type" field of the ICMP header. And each "type" and its "code" field and the last 4 bytes of the message header together express the information represented by each message type. These ICMP message types are mainly divided into error messages and query messages:

The query message mainly includes: echo request (TYPE8), echo response (TYPE0), request/response for address mask or timestamp, etc.
Error messages mainly include: target host unreachable (TYPE3), timeout, source suppression, route redirection, etc.
As the most typical application of the ICMP protocol, ping is mainly related to the two types of echo requests and echo responses, which are also the two types that this article mainly cares about. Of course, when the host is unreachable or the network route is unreachable, ping will receive the unreachable packet of the target host with a TYPE of 3 from the router (we can obtain it through tcpdump packet capture). For other types, interested students can learn by themselves, such as icmp redirection attacks and flood attacks are all network attacks that use the ICMP protocol.

Second, write a simple ping to understand Linux ping

As one of the protagonists of this article, ping, it is necessary to write a simple ping to help us better understand the entire request response process. My own test machine, centos 7, uses the iputils tool for ping, so we can learn how to write a simple ping from the iputils source code.

Anyone who has studied c network programming must understand the concept of socket sockets. For ping, sending requests and receiving replies are also done through sockets. However, although the ICMP protocol is an L4 layer protocol similar to TCP and UDP in the kernel, it is essentially a network layer protocol attached to the IP protocol, so it is necessary to use raw sockets (SOCK_RAW) to build sockets, not TCP or Stream sockets (SOCK_STREAM) and packet sockets (SOCK_DGRAM) used by UDP. The purpose of SOCK_RAW is that the user can customize the filling of the IP header, and customize the ICMP header for ICMP messages. The following picture shows the logic of sending the entire ping and processing the response in the code.

The specific code can refer to this: The whole process is very simple. It should be noted that for ping, the program is very likely to receive an echo with type 0 first. A request message is received, and then an echo response message with type 8 is received. This is because icmp packets can be received and processed by the kernel at the same time as they are processed by raw sockets, as described in the Understanding Linux Network Internals book below.

3. Before adding the kernel code, you only need to know a structure and icmp.c

Having understood the whole process of ping, the next step is to modify the kernel to convey what you want to say. But most importantly, you need to analyze the location of the modification, that is, where in the kernel code the bytes that the echo reply might send. There is a very important structure here - struct sk_buff, whose definition is located in .

The sk_buff structure in the kernel does not need to be copied or deleted, so that data is transmitted between protocols at various layers—that is, the way to move the pointer head, specifically, when dealing with different protocol headers, the pointer representing the protocol header, It points to different data areas (for example, from L2 to L4 layer protocols, respectively point to the second-layer mac header, the third-layer IP header, and the fourth-layer transmission header). The following are descriptions of several important and confusing fields, combined with schematic descriptions:

The figure above briefly illustrates the relationship between the four pointers and the pointed area. In addition, for the relationship between data_len and len, if it is assumed that the icmp packet is relatively small and the ip layer will not fragment it, then data_len is 0, and len is the length of the current protocol header + the length of the data packet. The relationship between data_len and len involves the related content of the skb_shared_info structure. Because it has little to do with the center of the article, interested students can check the article by themselves to learn
The data pointer and the len characterizing the data length of the protocol layer in the above content are directly related to the data pointed to by the sk_buff modified later. In addition, sk_buff is associated with many other structures. Here we only briefly explain the meaning of some important fields. For more specific and detailed descriptions, please refer to Chapter 2 of Understanding Linux Network Internal or series of articles for more in-depth study.

After understanding the sk_buff structure, you need to locate the file that processes the icmp protocol. icmp.c is located in the kernel directory net/ipv4/icmp.c, and the ICMP protocol is usually compiled into the kernel statically rather than configured through modules. Here I pulled out a Big Picture from the book Understanding Linux Network Internal to briefly explain how the sk_buff structure object is passed in many functions in icmp for the echo request sent by ping.

First, ip_local_deliver_finish will pass the ICMP message to icmp_rcv, and icmp_rcv will parse the type field in the icmp header. For the type of query message (such as type8), it will be passed to icmp_reply, and the error message will be passed to icmp_send for processing, and the ICMP protocol will also Interact with other protocols such as TCP/UDP to transfer information. For the request sent by the ping process, it will be passed to the icmp_echo function for processing. And icmp_echo is a very important step in processing the ping request. The kernel will copy the part of the data packet attached to the request intact and send it back to the source host. So we can add our "love statement" to the icmp_echo function.

static bool icmp_echo(struct sk_buff *skb)
struct net *net;
net = dev_net(skb_dst(skb)->dev);
if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
struct icmp_bxm icmp_param; = *icmp_hdr(skb); = ICMP_ECHOREPLY;
icmp_param.skb = skb;
//------------Add start -------------
char sentence1[] = "I LOVE U, xxxx.";
char sentence2[] = "I MISS U, xxxx.";
char sentence3[] = "Happy Valentine's Day!";
int sentence_len_list[] = {sizeof(sentence1), sizeof(sentence2), sizeof(sentence3)};
char* sentence_list[] = {sentence1, sentence2, sentence3};
int sentence_index = % 3;
if(skb->len >= 16 + sentence_len_list[sentence_index])
char* tmp = (char*)(skb->data+16);
char* target_sentence = sentence_list[sentence_index];
int i=0;
for(;i {
tmp[i] = target_sentence[i];
for(;i < skb->len-16;++i)
tmp[i] = 0;
//------------Add end------------
icmp_param.offset = 0;
icmp_param.data_len = skb->len;
icmp_param.head_len = sizeof(struct icmphdr);
icmp_reply(&icmp_param, skb);
/* should there be an ICMP stat for ignored echos? */
return true;
The icmp_bxm structure in the above code contains all the required information in the subsequent icmp message transfer process, including the icmp message header, the sk_buff object, the icmp message payload size, etc. It should be noted that since icmp_rcv has parsed the header part of the icmp protocol in sk_buff, skb->data in the parameter points to the icmp data part, that is, it does not contain the message header, and skb->len also only has icmp The length of the data section. Assuming that the data part carried in the ping request is 56 bytes, the size of skb->len is 56 at this time. Since the first 16 bytes of the ping data part carry the struct timeval object sent - the time when sending, so in the actual replacement, start from the 16th byte of the data part pointed to by data, and use memcpy to copy it to the corresponding area, or the silly loop assignment as in the example above. The above code indicates that the above three sentences are cyclically replied according to the seq_id in the echo request. Of course, creative partners can increase the difficulty of expression.

4. Create an Alibaba Cloud ECS server and complete all modifications in ten minutes

After analyzing the entire icmp processing flow and modification method, we only need to create an Alibaba Cloud ECS and simply compile the modified kernel. The specific process is as follows:

Alibaba Cloud creates a server of any size (large size can speed up kernel compilation, a 4vcpu server is created here), and centos is used as os
Download the linux kernel code, decompress it and place it in the /usr/src/kernels directory. This article uses the 4.20.6 kernel version.
Before compiling, based on the config file in the /boot directory of the original centos system, generate a compilation configuration item, and customize the kernel according to this compilation item. Copy the original configuration file to the kernel file directory sudo cp /boot/config-3.10.0-693.el7.x86_64 ./.config; execute make oldconfig, generate a new .config file
Compile the source code: make -j 4 , some libraries may be missing during the compilation process. At this time, yum installs the missing libraries, such as openssl-devel, elfutils-libelf-devel
Install kernel modules: make modules_install -j 4
Copy the kernel and configuration files to the /boot directory and generate the file: make install -j 4
Update boot: grub2-mkconfig -o /boot/grub2/grub.cfg
Modify the default default boot boot kernel: modify the /etc/default/grub file, set GRUB_DEFAULT to 0, 0 means the first boot item, which is the latest compiled kernel.
Restart the server: reboot
At this point, tell your goddess/male god that everything you want to say is in the ping.

Some reference articles:

Understanding Linux Network Internal Chapter 2 & Chapter 25

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone Contact Us