crackpipe.c is a program that utilizes the linux Ethertap device to tunnel IP's over normal TCP/UDP connections. Being actively developed.
5e449f0dee5926d3ab0389a1c8a4b1e5f93bb61aef893f3d24d56dce4239fa17
/* 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 <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <fcntl.h>
/* 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 <host | -> <port>
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. */