/* crackpipe.c -- uses the ethertap stuff to try to tunnel an IP, without using ipip, to break through firewalls. May the world's fascist admins rot in hell for their port-blocking policies. */ /* usage information is in comments at the very end of this file */ #include #include #include #include #include #include #include #include /* define TCP or UDP here so we can decide how we'd like to connect. */ #define UDP #undef TCP /* maximum size to use for the copy buffer */ /* setting the MTU of the tap device to something bigger than this would probably be a bad idea, methinks */ #define BUFSIZE 4096 /* also, the mtu for the tap device must be smaller than the mtu of your connection to the net... if it's not, packets will be chopped up in transit.. looking at this, I'd say you've gotta have 16 bytes difference, at least, but what's the point in pushing your luck. go for a couple hundered or so, so if your ethernet uses an MTU of 1500, do something like 1200 for safety when you ifconfig tap0 */ void selectloop(int netfd, int tapfd); void usage(void); char buffer[BUFSIZE]; main(int ac, char *av[]) { int destport; struct sockaddr_in destaddr; struct hostent *ht; int sock; int daemon; int netfd; int tapfd; /* check for a sane number of parameters */ if(ac != 3) usage(); /* get port number, bail if atoi gives us 0 */ if((destport = atoi(av[2])) == 0) usage(); /* check if we're a daemon or if we will connect. */ if(av[1][0] == '-') daemon = 1; else daemon = 0; if(!daemon) { /* resolve DNS */ if((ht = gethostbyname(av[1])) == NULL) { switch(h_errno) { case HOST_NOT_FOUND: printf("%s: Unknown host\n", av[2]); break; case NO_ADDRESS: printf("%s: No IP address for hostname\n", av[2]); break; case NO_RECOVERY: printf("%s: DNS Error\n", av[2]); break; case TRY_AGAIN: printf("%s: Try again (DNS Fuckup)\n", av[2]); break; default: printf("%s: Unknown DNS error\n", av[2]); } exit(0); } /* set up the destaddr struct */ destaddr.sin_port = htons(destport); destaddr.sin_family = AF_INET; memcpy(&destaddr.sin_addr, ht->h_addr, ht->h_length); } #ifdef TCP sock = socket(AF_INET, SOCK_STREAM, 0); #endif #ifdef UDP sock = socket(AF_INET, SOCK_DGRAM, 0); #endif if(sock == -1) { perror("socket"); exit(0); } printf("Opening network socket.\n"); if(!daemon) { if(connect(sock, &destaddr, sizeof(struct sockaddr_in)) == -1) { perror("connect"); exit(0); } netfd = sock; } else { struct sockaddr_in listenaddr; #ifdef UDP struct sockaddr_in remote; #endif int socklen; listenaddr.sin_port = htons(destport); listenaddr.sin_family = AF_INET; listenaddr.sin_addr.s_addr = inet_addr("0.0.0.0"); if(bind(sock, &listenaddr, sizeof(struct sockaddr_in)) == -1) { perror("bind"); exit(0); } socklen = sizeof(struct sockaddr_in); #ifdef TCP if(listen(sock, 1) == -1) { perror("listen"); exit(0); } printf("Waiting for TCP connection...\n"); if((netfd = accept(sock, &listenaddr, &socklen)) == -1) { perror("accept"); exit(0); } #else /* TCP */ netfd = sock; recvfrom(netfd, buffer, BUFSIZE, MSG_PEEK, &remote, &socklen); connect(netfd, &remote, socklen); #endif } /* right. now, we've got netfd set to something which we're going to be able to use to chat with the network. */ printf("Opening /dev/tap0\n"); tapfd = open("/dev/tap0", O_RDWR); if(tapfd == -1) { perror("tapfd"); exit(0); } selectloop(netfd, tapfd); return 0; } void selectloop(int netfd, int tapfd) { fd_set rfds; int maxfd; int len; if(netfd > tapfd) maxfd = netfd; else maxfd = tapfd; while(1) { FD_ZERO(&rfds); FD_SET(netfd, &rfds); FD_SET(tapfd, &rfds); if(select(maxfd+1, &rfds, NULL, NULL, NULL) == -1) { perror("select"); exit(0); } if(FD_ISSET(netfd, &rfds)) { FD_CLR(netfd, &rfds); if((len = read(netfd, buffer, BUFSIZE)) < 1) { if(len == -1) perror("read_netfd"); printf("netfd died, quitting\n"); close(tapfd); exit(0); } printf("%d bytes from network\n", len); write(tapfd, buffer, len); continue; } if(FD_ISSET(tapfd, &rfds)) { FD_CLR(tapfd, &rfds); if((len = read(tapfd, buffer, BUFSIZE)) < 1) { if(len == -1) perror("read_tapfd"); printf("tapfd died, quitting\n"); shutdown(netfd, 2); close(netfd); exit(0); } printf("%d bytes from interface\n", len); write(netfd, buffer, len); continue; } } /* end of looping */ } void usage(void) { printf("You fucked up the arguments.\n"); exit(0); } /* songs of firewalls, by the crackpipe author, just for some interesting source reading. */ /* firewall song #1, to the tune of "the beverly hillbillies" */ /* ohhhh, lemme tell you a story about a man who's lame this nasty admin oughta hang his head in shame, thought one day "this network's kinda loose" into his mind poured a bubblin' ooze... */ /* "firewalls," he thought... no mail, no dns... */ /* well, the users decided, this shit has gotta go we just need the proper sexy hunk of code, well, crackpipe came and broke a hole on through, and gave the bastards a needed "fuck you"... */ /* hmmmm. need to finish that eventualy */ /* alright, this should tell you how to use this fucker... well, hopefully... */ /* alright, the args go something like this: crackpipe the first argument is either the hostname to connect to, or, if you're the host which will be listening, a -.. obviously, the system inside the firewall gives the hostname, and the free system gives the -. both sides must specify a port #... this should, clearly, be the same for both ends... that should explain it.. */ /* oh, also, here's what you'll need to turn on in the linux kernel -- first, you'll need a kernel in the later 2.1 range... I'd say from 2.1.80 up should be cool, but I'm not positive about that.. if all of the config options I mention below aren't present, it's too old. in the "Networking Options" section, turn on: "Kernel/User netlink socket" and, just below, "Netlink device emulation" also, in the "Network device support" section, turn on: "Ethertap network tap" if those are compiled in, your kernel is set. */ /* configuring the ethertap device -- first, the necessary /dev files need to exist, so run: mknod /dev/tap0 c 36 16 to get that to exist. next, you have to ifconfig the ethertap device, so pick a subnet you're going to use for that. in this example, we're going to use the network 192.168.1.0, with one side as 192.168.1.1, and the other as 192.168.1.2... so, you'll need to do: ifconfig tap0 192.168.1.1(or .2) mtu 1200 (see the notes at the beginning for a good size for the mtu value. basically, it's got to be lower than the mtu value listed for eth0 when you run ifconfig) 2.1 kernels should create the needed route automatically, so that shouldn't be a problem. */ /* hopefully, no matter how 14m3 you are, that will give you some idea of what you need to do, config-wise. if not, well, then ask some '1337 linux-guru type d00d, and hopefully he can get the routing and shit right. */