经常使用别个共享的梯子的人要注意了,你的隐私去哪儿了?
把HTTP请求的URL全部记录下来,vps上用的~~ 日志记录在 “/var/log/url_record.txt” 程序守护进程方式运行在后台
pptp类型的vpn,每个vpn用户登录的时候,系统会创建一个虚拟网卡pppx, 程序捕获到事件后会自动一个线程针对这个虚拟网卡抓包
Debian/Ubuntu: apt-get install libpcap-dev -y
CentOS:yum install libpcap-devel -ygcc -o url_recorder url_recorder.c -lpcap -lpthread
需要root权限
./url_recoder
代码:
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <sys/types.h> |
5 | #include <sys/socket.h> |
6 | #include <linux/if.h> |
7 | #include <netinet/in.h> |
8 | #include <linux/netlink.h> |
9 | #include <linux/rtnetlink.h> |
10 | #include <arpa/inet.h> |
11 | #include <pcap.h> |
12 | #include <unistd.h> |
13 | #include <time.h> |
14 | #include <pthread.h> |
15 |
16 | #define PROMISC 1 |
17 | #define SNAPLEN 1600 |
18 |
19 | static char log_file[] = "/var/log/url_record.txt" ; |
20 | static char pidfile[] = "/var/run/url_recorder" ; |
21 | static FILE * log_fp; |
22 | static pthread_mutex_t log_mutex; |
23 | static char nic_bitmap[20]; |
24 | static char nic[10]; |
25 |
26 | int log_init() |
27 | { |
28 | int ret; |
29 | |
30 | pthread_mutex_init(&log_mutex,NULL); |
31 | log_fp = fopen (log_file, "a+" ); |
32 | if (log_fp == NULL){ |
33 | printf ( "open log file failedn" ); |
34 | } |
35 | |
36 | return 0; |
37 | } |
38 |
39 | int logging( char *data, int len) |
40 | { |
41 | time_t timet; |
42 | struct tm *p; |
43 | char str_time[100]; |
44 |
45 | timet = time (NULL); |
46 | p = localtime (&timet); |
47 | |
48 | pthread_mutex_lock(&log_mutex); |
49 |
50 | strftime (str_time, sizeof (str_time), "<--%m-%d %H:%M:%S--> " ,p); |
51 | fwrite (str_time, strlen (str_time),1,log_fp); |
52 | fwrite (data,len,1,log_fp); |
53 | fputc ( 'n' ,log_fp); |
54 | fflush (log_fp); |
55 |
56 | pthread_mutex_unlock(&log_mutex); |
57 |
58 | return 0; |
59 | } |
60 |
61 | int create_pidfile() |
62 | { |
63 | return 0; |
64 | } |
65 |
66 |
67 | int is_http_request( const unsigned char * buf, int len) |
68 | { |
69 | if (buf[0] == 'G' && buf[1] == 'E' && buf[2] == 'T' ){ |
70 | return 1; |
71 | } |
72 |
73 | if (buf[0] == 'P' && buf[1] == 'O' && buf[2] == 'S' && buf[3] == 'T' ){ |
74 | return 2; |
75 | } |
76 |
77 | return 0; |
78 | } |
79 |
80 | int http_hdr_len( const unsigned char * buf, int len) |
81 | { |
82 | int i = 0; |
83 | int hdr_len = 0; |
84 |
85 | for (i = 0; i < len - 3; i++){ |
86 | if (buf[i] == 'r' && buf[i + 1] == 'n' |
87 | && buf[i + 2] == 'r' && buf[i + 3] == 'n' ){ |
88 | hdr_len = i; |
89 | break ; |
90 | } |
91 | } |
92 |
93 | return hdr_len; |
94 |
95 | } |
96 |
97 | int get_url(unsigned char * buf, int *url_len, const unsigned char *pkt_data, int hdr_len) |
98 | { |
99 | const unsigned char * cur; |
100 | int host_len; |
101 | int uri_len; |
102 |
103 | memcpy (buf, "http://" , 7); |
104 | buf += 7; |
105 | *url_len = 7; |
106 |
107 | cur = strstr (pkt_data, "Host:" ); |
108 | if (cur == NULL) |
109 | return -1; |
110 | cur += 6; |
111 | host_len = field_len(cur, hdr_len - (cur - pkt_data)); |
112 |
113 | if (host_len && (*url_len +host_len<1200)){ |
114 | memcpy (buf, cur, host_len); |
115 | buf += host_len; |
116 | *url_len += host_len; |
117 | } |
118 | else |
119 | { |
120 | return -1; |
121 | } |
122 |
123 | cur = pkt_data; |
124 | if (pkt_data[0] == 'G' ) |
125 | cur += 4; |
126 | else if (pkt_data[0] == 'P' ){ |
127 | cur += 5; |
128 | } |
129 |
130 | uri_len = field_len(cur, hdr_len - (cur - pkt_data)); |
131 | uri_len -= 9; |
132 |
133 | if ((*url_len + uri_len) < 1200){ |
134 | memcpy (buf, cur, uri_len); |
135 | *url_len += uri_len; |
136 | } |
137 | |
138 | return 0; |
139 | |
140 | } |
141 |
142 | int field_len( const unsigned char * buf, int len) |
143 | { |
144 | int i = 0; |
145 | int field_len = 0; |
146 | |
147 | for (i = 0; i < len-1; i++){ |
148 | if (buf[i] == 'r' && buf[i + 1] == 'n' ){ |
149 | field_len = i; |
150 | break ; |
151 | } |
152 | } |
153 |
154 | return field_len; |
155 | } |
156 |
157 | int is_tcp( const unsigned char * buf, int len) |
158 | { |
159 | if (len < 54) |
160 | return 0; |
161 | |
162 | //l2proto = Linux cooked capture |
163 | //if (buf[12] != 0x08 || buf[13] != 0x00){ |
164 | if (buf[14] != 0x08 || buf[15] != 0x00){ |
165 | return 0; |
166 | } |
167 | |
168 | //if (buf[23] != 0x06){//tcp flag |
169 | if (buf[25] != 0x06){ //tcp flag |
170 | return 0; |
171 | } |
172 |
173 | return 1; |
174 | } |
175 |
176 | void callback(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *bytes) |
177 | { |
178 | int len; |
179 | const unsigned char *buf; |
180 | const unsigned char *cur; |
181 | unsigned char url[1024]; |
182 | int url_len = 0; |
183 | char data[1400]; |
184 | int is_req; |
185 | int hdr_len; |
186 | int ret; |
187 |
188 | buf = bytes; |
189 | len = h->caplen; |
190 | cur = buf; |
191 |
192 | if (!is_tcp(buf, len)){ |
193 | return ; |
194 | } |
195 |
196 | //cur += 54; |
197 | //len -= 54;//tcp hdr ip hdr |
198 | cur += 56; |
199 | len += 56; |
200 |
201 | is_req = is_http_request(cur, len); |
202 | hdr_len = http_hdr_len(cur, len); |
203 |
204 | switch (is_req){ |
205 | case 0: |
206 | break ; |
207 | case 1: |
208 | ret = get_url(url,&url_len, cur, hdr_len); |
209 | if (ret == 0){ |
210 | logging(url,url_len); |
211 | //printf("url_len:%dn",url_len); |
212 | } |
213 | break ; |
214 | case 2: |
215 | ret = get_url(url,&url_len, cur, hdr_len); |
216 | if (ret == 0){ |
217 | logging(url,url_len); |
218 | } |
219 | //get_data(data, curl, len); |
220 | break ; |
221 | default : |
222 | break ; |
223 | } |
224 | } |
225 |
226 |
227 | void *capture_thread( void * arg) |
228 | { |
229 |
230 | char dev[10]; |
231 | pcap_t *pt; |
232 | char errbuf[PCAP_ERRBUF_SIZE]; |
233 |
234 | strcpy (dev,( char *)arg); |
235 | dev[9] = 0; |
236 |
237 | |
238 | pt = pcap_open_live(dev, SNAPLEN, PROMISC, -1, errbuf); |
239 | if (pt == NULL){ |
240 | printf ( "open dev failedn" ); |
241 | return ; |
242 | } |
243 |
244 | pcap_loop(pt, -1, callback,NULL); |
245 | // pthread_detach(pthread_self()); |
246 | printf ( "capture thread createn" ); |
247 |
248 | } |
249 |
250 | int start_capture( char *dev) |
251 | { |
252 |
253 | char dev_vpath[30] = "/sys/class/net/" ; |
254 | pthread_t thread ; |
255 | pthread_attr_t attr; |
256 |
257 | strcpy (nic,dev); |
258 | sleep(1); |
259 | strcat (dev_vpath,nic); |
260 | if (access(dev_vpath,0) == 0){ |
261 | int ret; |
262 | pthread_attr_init(&attr); |
263 | pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); |
264 | pthread_create(& thread ,&attr,capture_thread,nic); |
265 | pthread_attr_destroy(&attr); |
266 | } |
267 |
268 | return 0; |
269 | } |
270 |
271 |
272 | void parseBinaryNetLinkMessage( struct nlmsghdr *nlh) |
273 | { |
274 | int len = nlh->nlmsg_len - sizeof (*nlh); |
275 | struct ifinfomsg *ifi; |
276 |
277 | if ( sizeof (*ifi) > ( size_t )len){ |
278 | printf ( "Got a short messagen" ); |
279 | return ; |
280 | } |
281 |
282 | ifi = ( struct ifinfomsg*)NLMSG_DATA(nlh); |
283 | if ((ifi->ifi_flags & IFF_LOOPBACK) != 0){ |
284 | return ; |
285 | } |
286 |
287 | struct rtattr *rta = ( struct rtattr*) |
288 | (( char *)ifi + NLMSG_ALIGN( sizeof (*ifi))); |
289 | len = NLMSG_PAYLOAD(nlh, sizeof (*ifi)); |
290 |
291 | while (RTA_OK(rta,len)){ |
292 | switch (rta->rta_type){ |
293 | case IFLA_IFNAME: |
294 | { |
295 | char ifname[IFNAMSIZ]; |
296 | int up; |
297 | char id; |
298 | snprintf(ifname, sizeof (ifname), "%s" , |
299 | ( char *)RTA_DATA(rta)); |
300 | up = (ifi->ifi_flags & IFF_RUNNING)? 1 : 0; |
301 | if (up && ((ifname[0] == 'p' )&&(ifname[1] == 'p' )&& |
302 | (ifname[2] == 'p' ))){ |
303 | printf ( "msg from:%s" ,ifname); |
304 | sscanf (ifname+3, "%d" ,( int *)&id); |
305 | if (nic_bitmap[id]) |
306 | break ; |
307 | start_capture(ifname); |
308 | nic_bitmap[id] = 1; |
309 | printf ( "%s %dn" ,ifname,up); |
310 | } |
311 | if (!up && ((ifname[0] == 'p' )&&(ifname[1] == 'p' )&& |
312 | (ifname[2] == 'p' ))){ |
313 | sscanf (ifname+3, "%d" ,( int *)&id); |
314 | nic_bitmap[id] = 0; |
315 | printf ( "%s %dn" ,ifname,up); |
316 | } |
317 | } |
318 | } |
319 |
320 | rta = RTA_NEXT(rta,len); |
321 | } |
322 |
323 | } |
324 |
325 |
326 | int main( int argc, char ** argv) |
327 | { |
328 |
329 | struct sockaddr_nl addr; |
330 | struct nlmsghdr *nlh; |
331 | char buffer[4096]; |
332 | int sock,len; |
333 |
334 |
335 | daemon(0,0); |
336 | create_pidfile(); |
337 | log_init(); |
338 |
339 | |
340 | if ((sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE)) == -1){ |
341 | printf ( "open NETLINK_ROUTE socket failedn" ); |
342 | goto exit ; |
343 | } |
344 |
345 | memset (&addr,0, sizeof (addr)); |
346 | addr.nl_family = AF_NETLINK; |
347 | addr.nl_groups = RTMGRP_LINK |RTMGRP_IPV4_IFADDR; |
348 | |
349 | if (bind(sock,( struct sockaddr*)&addr, sizeof (addr)) == -1){ |
350 | printf ( "bind failedn" ); |
351 | goto exit ; |
352 | } |
353 |
354 | while ((len = recv(sock,buffer,4096,0)) > 0){ |
355 | nlh = ( struct nlmsghdr*)buffer; |
356 | while ((NLMSG_OK(nlh,len)) && (nlh->nlmsg_type != NLMSG_DONE)){ |
357 | if (nlh->nlmsg_type == RTM_NEWLINK){ |
358 | parseBinaryNetLinkMessage(nlh); |
359 | } |
360 | nlh = NLMSG_NEXT(nlh,len); |
361 | } |
362 | } |
363 |
364 | close(sock); |
365 | |
366 | exit : |
367 | exit (0); |
368 | } |