从零开始云服务器网卡抓包
- 一. 服务器上新增自己的用户
- 二. 添加组件libpcap
- 四. 安装测试环境
- 六. 编写demo代码
- 七. 正式项目代码编译
- 八. 结果展示
一. 服务器上新增自己的用户
我这边是ubuntu服务器,其默认username为ubuntu,使用创建服务器时候的密码通过ssh登录进来
- 新增用户
adduser lsy
2. 将用户lsy添加到root用户组
主要是需要在文件/etc/sudoers中加入用户信息
chmod 777 /etc/sudoers
编辑/etc/sudoers,插入下图内容,即可将用户加入root组
chmod 440 /etc/sudoers
二. 添加组件libpcap
wget http://www.tcpdump.org/release/libpcap-1.4.0.tar.gz
sudo apt install bison m4 flex libpcap-dev -y
cd ../libpcap-1.4.0
sudo ./configure
sudo make
sudo make install
四. 安装测试环境
sudo apt install nginx
六. 编写demo代码
下例代码是测试代码,仅将访问日志打印出来
#include <pcap.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <iostream>
#include <cstring>
#define HTTP_PORT 80
using namespace std;
#define ETH_ADDR_LENGTH 6
struct ethhdr {
unsigned char h_dst[ETH_ADDR_LENGTH];
unsigned char h_src[ETH_ADDR_LENGTH];
unsigned short h_proto;
}; // 14
struct ip_header {
u_int8_t hdrlen : 4,
ip_version : 4; // 版本和首部长度
u_int8_t ip_tos; // 服务类型
u_int16_t ip_len; // 总长度
u_int16_t ip_id; // 标识
u_int16_t ip_off : 13, // 片偏移
flag : 3;
u_int8_t ip_ttl; // 存活时间
u_int8_t ip_p; // 协议类型
u_int16_t ip_sum; // 校验和
struct in_addr ip_src, ip_dst; // 源地址和目的地址
};
struct tcp_header {
u_int16_t th_sport; // 源端口号
u_int16_t th_dport; // 目的端口号
u_int32_t th_seq; // 序列号
u_int32_t th_ack; // 确认号
u_int8_t th_offx2; // 数据偏移
u_int8_t th_flags; // 控制标记
u_int16_t th_win; // 窗口大小
u_int16_t th_sum; // 校验和
u_int16_t th_urp; // 紧急指针
};
void parse_http_header(char *data, int data_len) {
char *start = strstr(data, "GET");
if (start == NULL) {
start = strstr(data, "POST");
}
if (start == NULL) {
// 不是 HTTP 请求,不处理
return;
}
// 解析出 PATH
char *end = strstr(start, " HTTP/1.");
if (end == NULL) {
// 不是 HTTP 请求,不处理
return;
}
int path_len = end - start - 4;
char path[1024];
strncpy(path, start + 4, path_len);
path[path_len] = '\0';
printf("PATH: %s\n", path);
}
void handle_packet(u_char *user, const struct pcap_pkthdr *header, const u_char *pkt_data) {
// 解析 IP 头部
struct ethhdr *ethhdr_info = (struct ethhdr*) pkt_data;
struct ip_header *ip_hdr = (struct ip_header *) (pkt_data + sizeof(struct ethhdr));
if (ip_hdr->ip_p != IPPROTO_TCP) {
// 不是 TCP 协议,不处理
/* int i;
for(i=0;i<32;i++)
{
printf("%02X ", pkt_data[i+sizeof(struct ethhdr)]);
}
*/
//printf("\nherder:%x%x, ip_hdr->ip_p:%d\n",ip_hdr->ip_version, ip_hdr->hdrlen, ip_hdr->ip_p);
return;
}
// 解析 TCP 头部
struct tcp_header *tcp_hdr = (struct tcp_header *) (pkt_data + sizeof(struct ip_header) + sizeof(struct ethhdr));
if (ntohs(tcp_hdr->th_dport) != HTTP_PORT) {
// 不是 HTTP 请求,不处理
return;
}
{
int i;
// printf("off:%d, ip_len:%d \n", tcp_hdr->th_offx2, ntohs(ip_hdr->ip_len));
// for(i=0;i<ip_hdr->ip_len;i++)
// {
// printf("%02X ", pkt_data[i+sizeof(struct ethhdr)]);
// }
}
// printf("\n");
int data_len = ntohs(ip_hdr->ip_len) - sizeof(struct ip_header) - tcp_hdr->th_offx2/4;
if (data_len <= 1) {
// 没有数据,不处理
return;
}
// 打印源地址、目的地址和
printf("\nSRC: %s:", inet_ntoa(ip_hdr->ip_src));
{
int i;
for(i=0;i<6;i++)
{
printf(" %02X", ethhdr_info->h_src[i]);
}
}
printf("\nDST: %s:", inet_ntoa(ip_hdr->ip_dst));
{
int i;
for(i=0;i<6;i++)
{
printf(" %02X", ethhdr_info->h_dst[i]);
}
}
putchar('\n');
// printf("SEQ: %u\n", ntohl(tcp_hdr->th_seq));
// 解析 HTTP 头部
char *data = (char *) (pkt_data + sizeof(struct ip_header) + sizeof(struct ethhdr) + tcp_hdr->th_offx2/4);
printf("data:%s\n", data);
// printf("ip_len:%d, ip_header:%ld, tcp_header:%ld, body_len:%ld\n", ntohs(ip_hdr->ip_len), sizeof(struct ip_header), sizeof(struct tcp_header), strlen(data));
parse_http_header(data, data_len);
}
int main(int argc, char *argv[]) {
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle = pcap_open_live(argv[1], BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
cerr << "Error opening device: " << errbuf << endl;
return -1;
}
if (pcap_datalink(handle) != DLT_EN10MB) {
cerr << "Device not Ethernet" << endl;
return -1;
}
struct bpf_program fp;
char filter_exp[] = "dst port 80";
// char filter_exp[] = "";
if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) == -1) {
cerr << "Error compiling filter" << endl;
return -1;
}
if (pcap_setfilter(handle, &fp) == -1) {
cerr << "Error setting filter" << endl;
return -1;
}
pcap_loop(handle, -1, handle_packet, NULL);
pcap_freecode(&fp);
pcap_close(handle);
return 0;
}
七. 正式项目代码编译
- 下载必要工具
sudo apt install make cmake
- 下载项目源码
git clone https://gitee.com/lovejj77/http_grab.git
- 编译源码
cd http_grab
cd log4cpp
./configure
make
make install
cd http_grab
mkdir build
cd build
cmake ..
make
- 设置开机启动服务
vim /etc/rc.local
#在最后一行插入下述指令
/usr/local/sbin/http_grab eth0
#保存退出
八. 结果展示
注意:生产文件均位于/home/logs_file 目录下