如何给UNIX域Socket套接字抓包?
Posted rtoax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何给UNIX域Socket套接字抓包?相关的知识,希望对你有一定的参考价值。
目录
源代码
https://github.com/Rtoax/test/tree/master/ipc/socket/unsocket-pcap
client.c
#include "common.h"
void main()
int connect_fd;
int ret = 0, len;
connect_fd = unsocket_client(UNIX_DOMAIN);
int val = 1;
setsockopt(connect_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
printf("fd: %d\\n", connect_fd);
while(1)
scanf("%s", buf);
ret = write(connect_fd, buf, strlen(buf));
printf("send bytes = %d: %s\\n", ret, buf);
len = read(connect_fd, buf, MSG_LENGTH);
printf("%d:%s\\n", len, buf);
close(connect_fd);
common.c
#include "common.h"
char buf[MSG_LENGTH];
int unsocket_server(const char *PATH)
struct sockaddr_un srv_addr;
int listen_fd, ret;
listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(listen_fd < 0)
return -1;
else
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, PATH, sizeof(srv_addr.sun_path)-1);
unlink(PATH);
ret = bind(listen_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
if(ret == -1)
close(listen_fd);
unlink(PATH);
return -1;
ret = listen(listen_fd, 1);
if(ret == -1)
close(listen_fd);
unlink(PATH);
return -1;
chmod(PATH, 00777);
return listen_fd;
int unsocket_client(const char *PATH)
int connect_fd;
int ret = 0;
static struct sockaddr_un srv_addr;
connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(connect_fd < 0)
return -1;
else
srv_addr.sun_family = AF_UNIX;
strcpy(srv_addr.sun_path, UNIX_DOMAIN);
ret = connect(connect_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
if(ret == -1)
close(connect_fd);
return -1;
return connect_fd;
common.h
#ifndef _COMMON_H
#define _COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include <termios.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/tcp.h>
#include <sys/mman.h>
#define UNIX_DOMAIN "./rtoax_unsocket_pcap"
#define MSG_LENGTH 1024
#define MAX_CLIENT_NUM 10
#define debug() printf("%s:%d\\n", __func__, __LINE__)
extern char buf[MSG_LENGTH];
int unsocket_server(const char *PATH);
int unsocket_client(const char *PATH);
#endif /*<_COMMON_H>*/
Makefile
ALL:
gcc server.c common.c -o server -lm
gcc client.c common.c -o client -lm
clean:
rm -f server client *.pcap
server.c
#include "common.h"
int listen_fd;
void sig_handler(int signum)
printf("------------------------------------------------\\n");
close(listen_fd);
exit(1);
void main()
int com_fd;
int ret = 0;
int i;
int len;
struct sockaddr_un clt_addr;
signal(SIGINT, sig_handler);
listen_fd = unsocket_server(UNIX_DOMAIN);
printf("------------------------------------------------\\n");
printf("-- UNIX Server %s\\n", UNIX_DOMAIN);
while(1)
len = sizeof(clt_addr);
com_fd = accept(listen_fd, (struct sockaddr*)&clt_addr, &len);
int val = 1;
setsockopt(listen_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
setsockopt(com_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
if(com_fd < 0)
perror("cannot accept client connect request.");
close(listen_fd);
unlink(UNIX_DOMAIN);
break;
memset(buf, 0, MSG_LENGTH);
while(1)
len = read(com_fd, buf, MSG_LENGTH);
printf("-- len= %d, recv: %s\\n", len, buf);
memset(buf, 0, MSG_LENGTH);
if(len<=0)
break;
buf[0] = 'X';
write(com_fd, buf, MSG_LENGTH);
close(com_fd);
undump.sh
#!/bin/bash
################################################################################
#
# UNIX域Socket抓包
#
# 作者:RToax
# 时间:2020年11月9日
#
################################################################################
exe_name=$0
eth_port="lo"
#UNIX socket 文件路径
unix_path=/tmp/unix.sock
unix_path_original="$unix_path.original"
ARG_UNIX_PATH="-u"
ARG_UNIX_PATH_S="UNIX socket path name."
#抓包文件
pcap_switch=0
pcap_file=pcap.pcap
ARG_PCAP_FILE="-f"
ARG_PCAP_FILE_S="Pcap File Name. default $pcap_file, no set no save."
#临时端口
tcp_port=8087
ARG_TCP_PORT="-p"
ARG_TCP_PORT_S="TMP port for swap UNIX socket. default $tcp_port"
#显示包的比特信息,如下:
# 0x0000: 4500 0034 52ae 4000 4006 ea13 7f00 0001
# 0x0010: 7f00 0001 c82a 07cf 6a88 73d9 bfa9 666c
# 0x0020: 8010 01f8 fe28 0000 0101 080a a2d6 9545
# 0x0030: a2d6 9545
pbits_flag=0
ARG_PBITS_DETAIL="-x"
ARG_PBITS_DETAIL_S="Show Packet Bits."
#帮助信息
ARG_USAGE="-h"
ARG_USAGE_S="Show usage."
#tcpdump的参数
ARG_TCPDUMP=" -i $eth_port -netvvv -N -q "
function usage()
printf "\\n"
printf "$exe_name [option] [value]\\n"
printf "\\n"
printf " $ARG_UNIX_PATH $ARG_UNIX_PATH_S \\n"
printf " $ARG_PCAP_FILE $ARG_PCAP_FILE_S\\n"
printf " $ARG_TCP_PORT $ARG_TCP_PORT_S\\n"
printf " $ARG_PBITS_DETAIL $ARG_PBITS_DETAIL_S\\n"
printf " $ARG_USAGE $ARG_USAGE_S\\n"
function parse_args()
argvs=($(echo "$@"))
elements=$[ $# - 1 ]
for (( i = 0; i <= $elements; i++ ))
# 解析抓包文件参数
if [ $argvs[$i] = $ARG_USAGE ]; then
usage
return 1
fi
# 解析UNIXsocket路径参数
if [ $argvs[$i] = $ARG_UNIX_PATH ]; then
unix_path=$argvs[$i+1]
#文件必须存在
if [ ! -e $unix_path ]; then
printf "Unix Path not exist. $unix_path\\n"
printf "TYPE>> $exe_name $ARG_USAGE for help.\\n"
return 1
fi
#文件必须为Socket类型
if [ ! -S $unix_path ]; then
printf "File must be Unix Socket Path. $unix_path\\n"
printf "TYPE>> $exe_name $ARG_USAGE for help.\\n"
return 1
fi
fi
# 解析抓包文件参数
if [ $argvs[$i] = $ARG_PCAP_FILE ]; then
pcap_file=$argvs[$i+1]
pcap_switch=1
if [ -e $pcap_file ]; then
printf "PCAP file: $pcap_file exist, overwrite it.\\n"
printf "TYPE>> $exe_name $ARG_USAGE for help.\\n"
rm -f $pcap_file
fi
fi
# 显示包的比特信息
if [ $argvs[$i] = $ARG_PBITS_DETAIL ]; then
pbits_flag=1
fi
# 解析临时端口参数
if [ $argvs[$i] = $ARG_TCP_PORT ]; then
tcp_port=$argvs[$i+1]
fi
return 0
if [ ! -e /usr/bin/socat ]; then
printf "Not socat found, install socat first.\\n"
exit 0
fi
if [ ! -e /usr/sbin/tcpdump ]; then
printf "Not tcpdump found, install tcpdump first.\\n"
exit 0
fi
#没有参数直接退出
if [ $# -lt 1 ]; then
usage
exit 0
fi
#解析参数
parse_args $*
#参数解析失败,直接退出
if [ $? -ne 0 ]; then
exit 0
fi
unix_path_original="$unix_path.original"
# Move socket files
mv "$unix_path" "$unix_path_original"
trap " rm '$unix_path'; mv '$unix_path_original' '$unix_path'; " EXIT
#创建一个TCP监听,一个UNIXSocket监听
socat -t100 "TCP-LISTEN:$tcp_port,reuseaddr,fork" "UNIX-CONNECT:$unix_path_original" &
#创建一个UNIX监听和一个TCP监听
socat -t100 "UNIX-LISTEN:$unix_path,mode=777,reuseaddr,fork" "TCP:localhost:$tcp_port" &
#ARG_TCPDUMP=" -i $eth_port -netvvv "
#端口过滤
ARG_TCPDUMP=$ARG_TCPDUMP" port $tcp_port "
#是否输出抓包文件
if [ $pcap_switch = "1" ]; then
ARG_TCPDUMP=$ARG_TCPDUMP" -w $pcap_file"
fi
if [ $pbits_flag = "1" ]; then
ARG_TCPDUMP=$ARG_TCPDUMP" -x"
fi
#保存抓包数据 -i lo -netvvv -x port $tcpport -w "$pcapfile"
tcpdump $ARG_TCPDUMP
测试
# ./undump.sh
./undump.sh [option] [value]
-u UNIX socket path name.
-f Pcap File Name. default pcap.pcap, no set no save.
-p TMP port for swap UNIX socket. default 8087
-x Show Packet Bits.
-h Show usage.
启动服务端程序,之后,启动抓包脚本:
# ./server
------------------------------------------------
-- UNIX Server ./rtoax_unsocket_pcap
启动脚本:
# ./undump.sh
./undump.sh [option] [value]
-u UNIX socket path name.
-f Pcap File Name. default pcap.pcap, no set no save.
-p TMP port for swap UNIX socket. default 8087
-x Show Packet Bits.
-h Show usage.
# ./undump.sh -u rtoax_unsocket_pcap -x
2020/11/09 15:46:03 socat[60255] E bind(5, AF=2 0.0.0.0:8087, 16): Address already in use
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
启动客户端:
# ./client
fd: 3
此时,抓包脚本启动的中断下将如下打印:
(多次测试时,会出现“Address already in use”问题,使用-p参数修改端口即可)。
# ./undump.sh -u rtoax_unsocket_pcap -x
2020/11/09 15:46:03 socat[60255] E bind(5, AF=2 0.0.0.0:8087, 16): Address already in use
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 74: (tos 0x0, ttl 64, id 53323, offset 0, flags [DF], proto TCP (6), length 60)
127.0.0.1.49498 > 127.0.0.1.simplifymedia: tcp 0
0x0000: 4500 003c d04b 4000 4006 6c6e 7f00 0001
0x0010: 7f00 0001 c15a 1f97 6d73 6e4d 0000 0000
0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a
0x0030: a2fe cf12 0000 0000 0103 0307
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 74: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
127.0.0.1.simplifymedia > 127.0.0.1.49498: tcp 0
0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001
0x0010: 7f00 0001 1f97 c15a 7fd1 b2c6 6d73 6e4e
0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a
0x0030: a2fe cf12 a2fe cf12 0103 0307
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 66: (tos 0x0, ttl 64, id 53324, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.49498 > 127.0.0.1.simplifymedia: tcp 0
0x0000: 4500 0034 d04c 4000 4006 6c75 7f00 0001
0x0010: 7f00 0001 c15a 1f97 6d73 6e4e 7fd1 b2c7
0x0020: 8010 0200 fe28 0000 0101 080a a2fe cf13
0x0030: a2fe cf12
在客户端发包,服务端接收:
# ./client
fd: 3
aaaaaaaaaaaaaaaaaaaaaaaaaaaa
send bytes = 28: aaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbb
send bytes = 25: bbbbbbbbbbbbbbbbbbbbbbbbb
抓包工具有如下打印:
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 94: (tos 0x0, ttl 64, id 53325, offset 0, flags [DF], proto TCP (6), length 80)
127.0.0.1.49498 > 127.0.0.1.simplifymedia: tcp 28
0x0000: 4500 0050 d04d 4000 4006 6c58 7f00 0001
0x0010: 7f00 0001 c15a 1f97 6d73 6e4e 7fd1 b2c7
0x0020: 8018 0200 fe44 0000 0101 080a a300 6e8e
0x0030: a2fe cf12 6161 6161 6161 6161 6161 6161
0x0040: 6161 6161 6161 6161 6161 6161 6161 6161
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 66: (tos 0x0, ttl 64, id 62517, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.simplifymedia > 127.0.0.1.49498: tcp 0
0x0000: 4500 0034 f435 4000 4006 488c 7f00 0001
0x0010: 7f00 0001 1f97 c15a 7fd1 b2c7 6d73 6e6a
0x0020: 8010 0200 fe28 0000 0101 080a a300 6e8e
0x0030: a300 6e8e
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 91: (tos 0x0, ttl 64, id 53326, offset 0, flags [DF], proto TCP (6), length 77)
127.0.0.1.49498 > 127.0.0.1.simplifymedia: tcp 25
0x0000: 4500 004d d04e 4000 4006 6c5a 7f00 0001
0x0010: 7f00 0001 c15a 1f97 6d73 6e6a 7fd1 b2c7
0x0020: 8018 0200 fe41 0000 0101 080a a300 8116
0x0030: a300 6e8e 6262 6262 6262 6262 6262 6262
0x0040: 6262 6262 6262 6262 6262 6262 62
00:00:00:00:00:00 > 00:00:00:00:00:00, IPv4, length 66: (tos 0x0, ttl 64, id 62518, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.simplifymedia > 127.0.0.1.49498: tcp 0
0x0000: 4500 0034 f436 4000 4006 488b 7f00 0001
0x0010: 7f00 0001 1f97 c15a 7fd1 b2c7 6d73 6e83
0x0020: 8010 0200 fe28 0000 0101 080a a300 8116
0x0030: a300 8116
分析结果无误:
以上是关于如何给UNIX域Socket套接字抓包?的主要内容,如果未能解决你的问题,请参考以下文章
Unix域套接字-Unix Domain Socket(转)