rendered paste body#define HTTPREQ "GET /blah HTTP/1.1\r\nHost: reply.me\r\nConnection: close\r\n\r\n" // should return HTTPCHECK string#define HTTPCHECK "proxycheckfound"#define RTIMEOUT 30#define WTIMEOUT 10#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <arpa/inet.h>#include <assert.h>#include <inttypes.h>#include <netdb.h>#include <netinet/in.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <ifaddrs.h>#include <net/if.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <pcap.h>#include <poll.h>#include <fcntl.h>struct ip_hdr_t{#if (BYTE_ORDER == LITTLE_ENDIAN) uint8_t ip_hl:4, ip_v:4;#elif (BYTE_ORDER == BIG_ENDIAN) uint8_t ip_v:4, ip_hl:4;#else #error "Adjust your <asm/byteorder.h> defines"#endif uint8_t ip_tos; uint16_t ip_len; uint16_t ip_id; uint16_t ip_off; uint8_t ip_ttl; uint8_t ip_p; uint16_t ip_sum; uint32_t ip_src; uint32_t ip_dst;}__attribute__((packed));struct tcp_hdr_t { uint16_t tcp_sport; uint16_t tcp_dport; uint32_t tcp_seq; uint32_t tcp_ackseq;#if (BYTE_ORDER == LITTLE_ENDIAN) uint8_t res:4, doff:4;#elif (BYTE_ORDER == BIG_ENDIAN) uint8_t doff:4, res:4;#else#error "Adjust your <asm/byteorder.h> defines"#endif uint8_t tcp_flags; uint16_t tcp_window; uint16_t tcp_sum; uint16_t tcp_urgptr;} __attribute__((packed));struct pkt { struct ip_hdr_t ip; struct tcp_hdr_t tcp;};struct iphash { uint32_t ip; struct iphash *next;};#define HSIZE 512#define SNAPLEN 128*1024struct pollfd *pollfds = NULL;#define BUFSZ 8188struct tentry { uint32_t t; uint8_t buf[BUFSZ];};struct tentry *tmap = NULL;int npoll = 0;int inflight=0;time_t now, oldnow;int poll_add(int fd, int events){ int i; for (i = 0; i < npoll; i++) { if (pollfds[i].fd == -1) break; } if (i == npoll) { pollfds = realloc(pollfds, sizeof(pollfds[0])*(++npoll)); tmap = realloc(tmap, sizeof(tmap[0])*(npoll)); } //printf("adding @ idx %d fd %d\n", i, fd); pollfds[i].fd = fd; pollfds[i].events = events; tmap[i].t = now; tmap[i].buf[0] = 0; inflight++; return i;}void poll_del(int idx){ //printf("deleting idx %d, fd %d\n", idx, pollfds[idx].fd); assert(pollfds[idx].fd != -1); pollfds[idx].fd = -1; pollfds[idx].events = 0; inflight--;}//struct iphash *hash[2048];uint8_t ipmap[1<<29];int check_map(uint32_t ip){ if (ipmap[ip/8] & (1<<(ip%8))) return 0; ipmap[ip/8] |= (1<<(ip%8)); return 1;}int make_connection(uint32_t ip, int port){ struct sockaddr_in sin; int sock; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); ip = htonl(ip); memcpy(&sin.sin_addr.s_addr, &ip, 4); assert((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))>=0); fcntl(sock, F_SETFL, O_NONBLOCK); connect(sock, (struct sockaddr *) &sin, sizeof(sin)); return sock;}int main(int argc, char *argv[]){ char buf[512]; int done; int dport; int probed=0; double total; double goal; int found=0; double rate; double irate; FILE *f; int sock; struct sockaddr_in sin; memset(&sin, 0,sizeof sin); char pcap_err[PCAP_ERRBUF_SIZE]; pcap_t *pc; int pc_off = 0; struct bpf_program filter; struct pcap_pkthdr ph; int pfd; FILE *fout; double penalty; int i; struct net *net; unsigned char *gotpk; struct pkt *rpkt; int finishers = 0; int repeats=0; double limit; int pks; int timedout = 0; signal(SIGPIPE, SIG_IGN); /* srcip srcif dstport srclist dstlist * 1 2 3 4 5 * */ assert(argc==4 && "srcif dstport dstlist"); assert(fout = fopen(argv[3], "a")); dport = strtol(argv[2], NULL, 10); pc = pcap_open_live(argv[1], sizeof(struct pkt) + 32, 0, 100, pcap_err); assert(pcap_setnonblock(pc, 1, pcap_err)==0); if (pcap_datalink(pc) == DLT_EN10MB) pc_off = 14; assert(pcap_compile(pc, &filter, "(ip proto \\tcp) and ((tcp[13] & (tcp-ack+tcp-rst)) = tcp-ack) and dst port 1337", 0, 0) != -1); assert(pcap_setfilter(pc, &filter) != -1); poll_add(pfd=pcap_fileno(pc), POLLIN); while (1) { poll(pollfds, npoll, 100); now = time(NULL); for (i = 0; i < npoll; i++) { int want = pollfds[i].events; int got = pollfds[i].revents; int fd = pollfds[i].fd; uint8_t *buf = tmap[i].buf; if (fd==-1) continue; if (got & (POLLERR|POLLHUP)) goto errclose; if ((got & want) == 0) continue; if (fd == pfd) { retry: gotpk = pcap_next(pc, &ph); if (!gotpk) continue; gotpk += pc_off; rpkt = (void*)gotpk; uint32_t gip = ntohl(rpkt->ip.ip_dst); uint32_t fip = ntohl(rpkt->ip.ip_src); if ((rpkt->tcp.tcp_dport == htons(1337)) && (rpkt->tcp.tcp_sport == htons(dport)) && check_map(fip)) { int cn = make_connection(fip, dport); int id = poll_add(cn, POLLOUT); strcpy(tmap[id].buf, HTTPREQ); probed++; } goto retry; } else { if (want == POLLOUT) { int tow = strlen(buf); int got = write(fd, buf, tow); if (got <= 0) { close(fd); poll_del(i); continue; } memmove(buf, buf + got, tow-got+1); tow -= got; if (!tow) { tmap[i].t = now; pollfds[i].events = POLLIN; buf[0] = 0; } } else { int rgot; int bufl = strlen(buf); rgot = read(fd, buf + bufl, BUFSZ - bufl - 1); if (rgot <= 0) { errclose:; close(fd); poll_del(i); continue; } tmap[i].t = now; bufl += rgot; buf[bufl] = 0; if (bufl < 16) continue; if (memcmp(buf + 9, "200", 3)) goto errclose; uint8_t *p = strstr(buf, "\r\n\r\n"); if (!p) { if (bufl == BUFSZ-1) goto errclose; continue; } p += 4; if (strstr(buf, HTTPCHECK)) { socklen_t sinlen = sizeof(sin); getpeername(fd, (struct sockaddr*)&sin, &sinlen); fprintf(fout, "%s\n", inet_ntoa(sin.sin_addr)); fflush(fout); found++; close(fd); poll_del(i); } } } } if (now < oldnow+3) continue; for (i = 0; i < npoll; i++) { int want = pollfds[i].events; int fd = pollfds[i].fd; if (fd == -1 || fd == pfd) continue; if ((want == POLLIN && tmap[i].t + RTIMEOUT < now) || (want == POLLOUT && tmap[i].t + WTIMEOUT < now)) { close(fd); poll_del(i); timedout++; } } oldnow = now; fprintf(stderr, "%d probed, %d timed out, %d inflight, %d found \r", probed, timedout, inflight, found); fflush(stdout); } return 0;}