home *** CD-ROM | disk | FTP | other *** search
- ---[ Phrack Magazine Volume 8, Issue 52 January 26, 1998, article 16 of 20
-
-
- -------------------------[ Piercing Firewalls
-
-
- --------[ bishnu@hotmail.com
-
-
- Introduction:
-
- Many ISPs manage a firewall to protect their users against the hostile
- Internet. While the firewall might protect the users, it also serves to limit
- their freedom.
-
- Most firewalls don't allow a connection to be established if the
- initiative is coming from the outside, as this automatically disables many
- security vulnerabilities. Unfortunately, this also means that many other
- things are not possible; for example, sending an X-display to a machine behind
- the firewall, or something similar.
-
- One solution is to ask the firewall administrator to configure the firewall
- not to disable X connections (or the port you plan to use. This normally
- means allowing connections on port 6000 to penetrate the firewall. But often
- the admin does not want to, as he is either too busy, hasn't figured out how
- to configure the firewall yet, or simply refuses to, as it violates the site
- security policy. Maybe you don't even want him to know that you plan to send
- some traffic backwards.
-
- For this purpose I wrote two simple programs that transmit TCP connections
- back thorough a tunnel, to your machine.
-
-
- The tunnel:
-
- The solution is two programs, one running at your machine, or some other
- machine behind the firewall, and another running at some *NIX-box on the
- Internet. The program behind the firewall (called tunnel) connects to a
- program (called portal) on the machine on the Internet. This connection
- probably won't be intercepted by the firewall (depending on the security
- policy), as it is outgoing. Once the connection from the tunnel to the portal
- is established, the portal opens a port for incoming TCP traffic, and we are
- ready to rock. Whenever a machine connects to the portal it sends the request
- back to the tunnel thorough the already established connection through the
- firewall, the tunnel will then forward the connection to your machine.
-
- The effect will be that you drag a port on your machine (or any machine
- behind the firewall) onto the other side of the firewall, which means that
- anyone can connect to it regardless of the site's security policy.
-
- An example:
-
- Goof: Your machine.
- Foo : Some other machine behind the firewall or same as Goof, running 'tunnel'.
- Bar : Some machine on the other side of the firewall running 'portal'.
- Boof: Some machine wanting to connect to machine Goof, or same as Bar.
-
- FIREWALL
- tunnel ^ portal
- ######### ^ #########
- # Foo #======================# Bar #
- ######### ^ #########
- | ^ |
- | ^ |
- | ^ |
- ######### ^ #########
- # Goof # ^ # Boof #
- ######### ^ #########
- FIREWALL
-
-
-
- You are sitting on machine Goof, and you run some program on machine Boof,
- this program happens to be using X-windows, so you want to send the display
- back to machine Goof. X-windows tries to establish a TCP connection through
- the firewall, which is 'burned'.
-
- So you start the tunnel on machine Foo, and set it to connect to machine
- Bar at lets say port 7000 (where the portal is running), also you set the
- tunnel to forward all TCP connections, coming back from the portal, to your
- machine Goof on port 6000 (X-windows). You start the portal on machine Bar,
- and you make it listen for the tunnel on port 7000. Once the tunnel has
- connected, the portal listens on port 6001 for incoming X. Whenever some
- X-application connects to the portal, the connection is passed to the tunnel,
- which then forwards it to machine Goof on port 6000.
-
- Finally on machine Boof you set your display to machine Bar:1 (in a tcsh
- type 'setenv DISPLAY bar:1', in bash 'export DISPLAY=bar:1'), which tells the
- application to use port 6001 (We can't use port 6000 if the machine is running
- a X-server itself). You start your Xeyes, and they pop in your face.
-
-
- Conclusion:
-
- If you use this program to cross a firewall you surely violate the ISP's
- security policy, as anybody can cross it as well, that is if they know, and
- there is nothing like security by obscurity. So don't tell your mom.
-
- An advantage of this approach is that you don't need to have root access on
- either machine, which is makes the whole process a bit easier.
-
- To compile the code, just do a `make`. It has been tested on
- Solaris 2.5.x, 2.6
- IRIX 6.[2,3,4]
- FreeBSD 2.1.5
- HPUX 10.x
- Linux 2.0.x
-
-
- ----[ THE CODE
-
-
- <++> tunnel/Makefile
- CC = gcc
-
- OSFLAGS =
- MYFLAGS = -Wall -O2 -g -pedantic
- CFLAGS = $(MYFLAGS) $(PROFILE) $(OSFLAGS)
-
- #If you compile on Solaris 2.x, uncomment the following line
- #LOCAL_LIBRARIES = -lsocket
-
- TUNNEL_OBJFILES = tunnel.o share.o
- PORTAL_OBJFILES = portal.o share.o
-
- all: tunnel portal
-
- tunnel : $(TUNNEL_OBJFILES) share.h
- $(CC) $(TUNNEL_OBJFILES) $(LOCAL_LIBRARIES) -o tunnel
- tunnel.o : tunnel.c share.h
- $(CC) -c $(CFLAGS) $(COMMFLAGS) tunnel.c
- portal : $(PORTAL_OBJFILES) share.h
- $(CC) $(PORTAL_OBJFILES) $(LOCAL_LIBRARIES) -o portal
- portal.o : portal.c share.h
- $(CC) -c $(CFLAGS) $(COMMFLAGS) portal.c
- share.o : share.c share.h
- $(CC) -c $(CFLAGS) $(COMMFLAGS) share.c
- clean:
- rm -f *.o tunnel portal core
- <-->
- <++> tunnel/tunnel.c
- /*
- -TUNNEL-
-
- This is the tunnel part of my firewall piercer. This code is supposed
- to be running on the inside of the firewall. The tunnel should then
- connect to the portal running on the outside.
-
- start it like:
- >% tunnel localhost 23 protal.machine.com 3001
-
- if the portal is running at port 3001 at portal.machine.com, incoming
- connections to the portal will get rerouted to this machines telnet
- port.
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <string.h>
- #include <signal.h>
- #include <errno.h>
- #include "share.h"
-
-
- extern char tunnel_buf[MAXLEN*2];
- char buf[MAXLEN*2];
- extern int tunnel_des; /* The socket destination of a tunnel packet*/
- extern int tunnel_src; /* The socket source of a tunel packet*/
- extern int tunnel_size; /* Size of tunnel packet*/
- extern struct connections connections; /*Linked list of connections*/
-
- char *remote_machine; /*remote machine name to tunnel to*/
- extern int tunnel_port; /*tunnel port*/
- extern int tunnel_sock; /*tunnel socket*/
- char *login_machine=""; /*machine to forward connections to*/
- int login_port; /*port to forward connections to*/
-
- int oldtime=0,ping_time=0;
- struct connection *descriptors[DESC_MAX];
- extern struct connection *descriptors[DESC_MAX];
- extern int errno;
- FILE *log=stdout; /*logfile = stdout by default*/
-
- void open_tunnel(){
- tunnel_sock=remote_connect(remote_machine,tunnel_port);
- }
-
-
- extern int optind;
- extern char *optarg;
-
- void usage(){
- printf("Usage: tunnel [-l logfile] <forward_machine> <forward_port>" \
- " <portal_machine> <portal_port>\n");
- printf("where:\n");
- printf("forward_machine is the machine to which the traffic is forwarded\n");
- printf("forward_port is the port to which the traffic is forwarded\n");
- printf("portal_machine is the machine we want to route the trafic from\n");
- printf("portal_port is the port we want to route the trafic from\n");
- printf("Coded by %s\n",AUTHOR);
- }
-
-
- /********************** Get the options ***********************/
-
- void get_options(int argc,char *argv[]){
- int c;
- while((c=getopt(argc,argv, "l:")) !=-1)
- switch(c){
- case 'l':
- if(!(log=fopen(optarg,"w"))){
- log=stdout;
- fprintf(log,"Unable to open logfile '%s':%s\n",
- optarg,strerror(errno));
- }
- break;
- case '?':
- default:
- usage();
- exit(-1);
- }
- /* the two next options*/
- if(argc-optind!=4){
- printf("Wrong number of options!\n");
- usage();
- exit(-1);
- }
- login_machine=get_ip(argv[optind++]);
- login_port=atoi(argv[optind++]);
- remote_machine=get_ip(argv[optind++]);
- tunnel_port=atoi(argv[optind++]);
- if(login_port<1||login_port>65535||tunnel_port<1||tunnel_port>65535){
- printf("Ports below 1 and above 65535 don't give any sense\n");
- usage();
- exit(-1);
- }
- }
-
- void alive(){
- /* To check wether the line is still alive, we Myping it every
- ALIVE_TIME seconds. If we don't get a ping from the tunnel
- every ALIVE_TIME*2 we disconnect the connection to the
- portal, and wait for a new. If the portal has not died, all
- the connections through the tunnel will continue as normal once
- the connection has been established again.
- The reason why I do this is because some firewalls tend to
- disable connections if there hasn't been any traffic for some time,
- or if the connection had been up too long time.
- */
-
- /*Transmit a Myping packet, we receive the
- answer in check_tunnel_connection()*/
- if(time(NULL)-oldtime>=ALIVE_TIME){
- oldtime=time(NULL);
- transmit_tunnel(buf,0,0,0);
- }
- if(time(NULL)-ping_time>ALIVE_TIME*2){
- printf("Connection to portal probably lost, hanging up.\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- }
- }
-
- int reset_selector(fd_set *selector,fd_set *errsel,struct connection *con)
- {
- /* We tell the selector to look on the tunnel socket aswell
- as our live connections.*/
- int maxsock,i;
- FD_ZERO(selector);
- FD_SET(tunnel_sock,selector);
- FD_SET(tunnel_sock,errsel);
- con=connections.head;
- maxsock=tunnel_sock;
- for(i=0;i<connections.num;i++,con=con->next){
- FD_SET(con->local_sock,selector);
- FD_SET(con->local_sock,errsel);
- maxsock=max(maxsock,con->local_sock);
- }
- return(maxsock); /*We return the maximum socket number*/
- }
-
- void check_tunnel_connection(fd_set *selector,fd_set *errsel,struct connection *con){
- /*Here we check the tunnel for incoming data*/
- if(FD_ISSET(tunnel_sock,errsel)){
- fprintf(log,"Tunnel connection terminated!\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- return;
- }
- if(FD_ISSET(tunnel_sock,selector)){
- if(receive_tunnel()!=-1){
- if(tunnel_src==0&&tunnel_des==0){ /*We have a Myping packet*/
- ping_time=time(NULL); /*reset the alive_timer*/
- }
- else if(tunnel_src==0){/*We have a 'hangup' signal for a connection*/
- if((con=descriptors[tunnel_des])){
- fprintf(log,"Removing connection to %s %d\n",con->host,con->port);
- removeconnection(con);
- }
- }
- else if(tunnel_des==0){ /*We have a new connection*/
- int newsock;
- if((newsock=remote_connect(login_machine,login_port))!=-1){
- connections.num++;
- con=(struct connection *)malloc(sizeof(struct connection));
- con->host=(char *)malloc(MAX_HOSTNAME_SIZE);
- strncpy(con->host,&tunnel_buf[4],MAX_HOSTNAME_SIZE);
- con->port=ntohl((((int *)tunnel_buf)[0]));
- con->local_sock=newsock;
- con->remote_sock=tunnel_src;
- con->time=time(NULL);
- con->next=connections.head;
- connections.head=con;
- descriptors[newsock]=con;
- fprintf(log,"Connected the incoming call from %s %d to %s %d\n",con->host,con->port,login_machine,login_port);
- /*Acknowledge the new connection to the portal*/
- transmit_tunnel(buf,0,con->local_sock,con->remote_sock);
- }
- }
- else if(descriptors[tunnel_des]){
- /*Send the data to the right descriptor*/
- writen(descriptors[tunnel_des]->local_sock,tunnel_buf,tunnel_size);
- }
- else{
- fprintf(log,"Connection to unallocated channel, hangup signal sent\n");
- /*Send a hangup signal to the portal, to disable the connection*/
- transmit_tunnel(buf,0,0,tunnel_src);
- }
- }
- }
- }
-
- void main(int argc,char **argv)
- {
- get_options(argc,argv);
- fprintf(log,"Opening tunnel to %s port %d\n",remote_machine,tunnel_port);
- fprintf(log,"Tunnelconnections will be forwarded to host %s"\
- " port %d\n",login_machine,login_port);
- connections.num=0;
- connections.head=NULL;
- signal(SIGINT,ctrlC);
- while(1){ /*The tunnel runs infinitely*/
- struct connection *con=connections.head;
- open_tunnel();
- ping_time=time(NULL);
- while(tunnel_sock!=-1){
- fd_set selector,errsel;
- struct timeval alive_time;
- alive_time.tv_sec=ALIVE_TIME;
- alive_time.tv_usec=0;
- alive(); /*Check wether the tunnelconnection is alive*/
- /* We have to listen to the tunnel and all the current connections.
- we do that with a select call*/
- if(select(reset_selector(&selector,&errsel,con)+1,
- &selector,NULL,&errsel,&alive_time)){
- /*Check for each of the local connections*/
- check_local_connections(&selector,&errsel,con);
- /*Check for the tunnel*/
- check_tunnel_connection(&selector,&errsel,con);
- }
- }
- sleep(RETRY_TIME); /*We sleep a while*/
- /* fprintf(log,"Trying to connect to portal.\n"); */
- }
- }
- <-->
- <++> tunnel/portal.c
- /*
- -PORTAL-
-
- This is the portal part of my firewall piercer. This code is supposed
- to be running on the outside of the firewall. The tunnel part should
- then connect trough the firewall to this program.
- start it like:
- >% portal 3000 3001
- for tunnel connection on port 3001 and incoming calls on 3000.
-
- when you connect to the portal at port 3000 your connection will be
- forwarded to the tunnel.
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <string.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <signal.h>
- #include <errno.h>
- #include "share.h"
-
- /***************/
- /* Global data */
- /***************/
- extern char tunnel_buf[MAXLEN*2];
- extern int tunnel_des;
- extern int tunnel_src;
- extern int tunnel_size;
- extern struct connections connections;
- extern struct connection *descriptors[DESC_MAX];
- extern int errno;
- extern int tunnel_port; /*tunnel port*/
- extern int tunnel_sock; /*tunnel new accepted socket*/
-
- char buf[MAXLEN*2];
- char *remote_machine; /*remote machine name*/
- int tunnel_basesock; /*tunnel base socket*/
- int local_sock; /* local port socket*/
- int local_port; /*local machine port*/
- FILE *log=stdout; /*logfile = stdout by default*/
- int ping_time=0;
-
-
- /********************** Usage ***********************/
- void usage(){
-
- fprintf(stderr,"Usage: portal [-l logfile] <local_port> <tunnel_port>\n");
- fprintf(stderr,"where:\n");
- fprintf(stderr,"local_port is the port where we accept incoming" \
- " connections\n");
- fprintf(stderr,"remote_port is the port where we accept the tunnel" \
- " to connect\n");
- fprintf(stderr,"Coded by %s\n",AUTHOR);
- }
-
- /********************** Get the options ***********************/
-
- extern int optind;
- extern char *optarg;
-
- void get_options(int argc,char *argv[]){
- int c;
- while((c=getopt(argc,argv, "l:")) !=-1)
- switch(c){
- case 'l':
- if(!(log=fopen(optarg,"w"))){
- log=stdout;
- fprintf(log,"Unable to open logfile '%s':%s\n",
- optarg,strerror(errno));
- }
- break;
- case '?':
- default:
- usage();
- exit(-1);
- }
- /* the two next options*/
- if(argc-optind!=2){
- printf("Wrong number of options!\n");
- usage();
- exit(-1);
- }
- local_port=atoi(argv[optind++]);
- tunnel_port=atoi(argv[optind++]);
- if(local_port<1||local_port>65535||tunnel_port<1||tunnel_port>65535){
- printf("Ports below 1 and above 65535 dont give any sense\n");
- usage();
- exit(-1);
- }
- }
-
- /*********************************************************/
- /*************** Portal *****************/
- /*********************************************************/
-
- void open_local_port(){
- /*Open the local port for incoming connections*/
- struct sockaddr_in ser;
- int opt=1;
- local_sock=socket(AF_INET,SOCK_STREAM,0);
- if(local_sock==-1){fprintf(log,"Error opening socket\n");exit(0);}
- if(setsockopt(local_sock,SOL_SOCKET,SO_REUSEADDR,
- (char *)&opt,sizeof(opt))<0)
- {perror("setsockopt REUSEADDR");exit(1);}
- ZERO((char *) &ser,sizeof(ser));
- ser.sin_family = AF_INET;
- ser.sin_addr.s_addr = htonl(INADDR_ANY);
- ser.sin_port = htons(local_port);
- if(bind(local_sock,(struct sockaddr *)&ser,sizeof(ser)) ==-1 ){
- fprintf(log,"Error binding to local port %d : %s\n"
- ,local_port,strerror(errno));
- exit(-1);
- }
- if(listen(local_sock,5)==-1){
- fprintf(log,"Error listening to local port %d : %s"
- ,local_port,strerror(errno));
- exit(-1);
- }
- fprintf(log,"Opened local port %d on socket %d\n",local_port,local_sock);
- }
-
- void open_portal(){
- int opt=0;
- struct sockaddr_in ser;
- if((tunnel_basesock=socket(AF_INET,SOCK_STREAM,0))==-1)
- {perror("socket");exit(-1);}
- if(setsockopt(tunnel_basesock,SOL_SOCKET,SO_REUSEADDR,
- (char *)&opt,sizeof(opt))<0)
- {perror("setsockopt REUSEADDR");exit(-1);}
- ZERO((char *) &ser,sizeof(ser));
- ser.sin_family = AF_INET;
- ser.sin_addr.s_addr = htonl(INADDR_ANY);
- ser.sin_port = htons(tunnel_port);
- if(bind(tunnel_basesock,(struct sockaddr *)&ser,sizeof(ser)) ==-1 ){
- fprintf(log,"Error binding to tunnel port %d : %s\n"
- ,tunnel_port,strerror(errno));
- exit(-1);
- }
- if(listen(tunnel_basesock,5)==-1){
- fprintf(log,"Error listening to tunnel port %d : %s"
- ,tunnel_port,strerror(errno));
- exit(-1);
- }
- }
-
- int accept_portal(){
- struct hostent *from;
- struct sockaddr_in cli;
- int newsock,clilen;
- clilen=sizeof(cli);
- if(!tunnel_basesock){return(-1);}
- /*Accept incoming calls*/
- newsock=accept(tunnel_basesock,(struct sockaddr *)&cli,&clilen);
- /*We want to know know our remote host better*/
- from=gethostbyaddr((char *)(&cli.sin_addr),sizeof(cli.sin_addr),PF_INET);
- if(!from){
- close(newsock);
- return(-1);
- }
- fprintf(log,"Tunnel connection from:%s %d\n",from->h_name,cli.sin_port);
- return(newsock);
- }
-
- void close_portal(){
- shutdown(tunnel_sock,1);
- close(tunnel_sock);
- }
-
- struct connection *receive_local(){
- struct sockaddr_in cli;
- int newsock,clilen;
- struct hostent *from;
- struct connection *con;
- clilen=sizeof(cli);
- /*Accept incoming calls*/
- newsock=accept(local_sock,(struct sockaddr *)&cli,&clilen);
- if(newsock==-1)
- {fprintf(log,"Server Accept Error:%s\n",strerror(errno));exit(-1);}
- /*We want to know know our remote host better*/
- from=gethostbyaddr((char *)(&cli.sin_addr),sizeof(cli.sin_addr), PF_INET);
- fprintf(log,"New connection from:%s %d\n",from->h_name,cli.sin_port);
- /*Add our new friend to our list of connections*/
- connections.num++;
- con=(struct connection *)malloc(sizeof(struct connection));
- con->host=strdup(from->h_name);
- con->port=cli.sin_port;
- con->local_sock=newsock;
- con->remote_sock=0;
- con->time=time(NULL);
- con->next=connections.head;
- connections.head=con;
- descriptors[newsock]=con;
- return(con);
- }
-
- void alive(){
- /* If we don't get a ping from the tunnel
- every ALIVE_TIME*2 we disconnect the connection to the
- tunnel, and wait for a new. If the tunnel has not died, all
- the connections from the tunnel will continue as normal once
- the connection has been established again*/
- if(time(NULL)-ping_time>ALIVE_TIME*2){
- printf("Connection to tunnel probably lost, hanging up.\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- }
- }
-
- int reset_selector(fd_set *selector,fd_set *errsel,struct connection *con){
- /* We tell the selector to look on the tunnel socket aswell
- as our live connections, and the connection socket.*/
- int maxsock,i;
- FD_ZERO(selector);
- FD_SET(local_sock,selector);
- FD_SET(tunnel_sock,selector);
- FD_SET(local_sock,errsel);
- FD_SET(tunnel_sock,errsel);
- con=connections.head;
- maxsock=max(local_sock,tunnel_sock);
- for(i=0;i<connections.num;i++,con=con->next){
- FD_SET(con->local_sock,selector);
- FD_SET(con->local_sock,errsel);
- maxsock=max(maxsock,con->local_sock);
- }
- return(maxsock);
- }
-
- void check_tunnel_connection(fd_set *selector,fd_set *errsel,struct connection *con){
- /*Here we check the tunnel for incoming data*/
- if(FD_ISSET(tunnel_sock,errsel)){
- fprintf(log,"Tunnel connection terminated!\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- return;
- }
- if(FD_ISSET(tunnel_sock,selector)){
- if(receive_tunnel()!=-1){
- if(tunnel_src==0&&tunnel_des==0){ /*We got a Myping*/
- ping_time=time(NULL);
- /* Ping the tunnel back!*/
- transmit_tunnel(buf,0,0,0); /*Send a Myping back*/
- }
- else if(tunnel_des){
- if(descriptors[tunnel_des]){
- con=descriptors[tunnel_des];
- if(tunnel_src!=0){
- con->remote_sock=tunnel_src;
- writen(descriptors[tunnel_des]->local_sock,tunnel_buf,tunnel_size);
- }
- else{
- printf("Hangup signal received. Removing connection to %s %d\n",con->host,con->port);
- removeconnection(con);
- }
- }
- }
- }
- }
- }
-
- void check_connection_port(fd_set *selector,fd_set *errsel,struct connection *con){
- /*Here we check the connection port for new connections*/
- if(FD_ISSET(local_sock,selector)){
- con=receive_local();
- if(con){
- printf("Transmitting the new connection\n");
- *((int *)(&buf[4]))=htonl(con->port);
- strncpy(&buf[8],con->host,MAX_HOSTNAME_SIZE);
- *(&buf[8]+strlen(con->host))=0;
- transmit_tunnel(buf,4+min(strlen(con->host)+1,MAX_HOSTNAME_SIZE),con->local_sock,0);
- }
- }
- }
-
- void main(int argc,char **argv){
- get_options(argc,argv);
- init_descriptors();
- connections.num=0;
- connections.head=NULL;
- remote_machine=get_ip(argv[2]);
- fprintf(log,"Tunneling incoming calls on port %d to port %d \n"
- ,local_port,tunnel_port);
- connections.num=0;
- connections.head=NULL;
- fprintf(log,"Opening portal\n");
- open_portal();
- signal(SIGINT,ctrlC);
- fprintf(log,"Opening localport\n");
- open_local_port();
- while(1){
- fprintf(log,"Waiting for tunnel connection on port %d\n",tunnel_port);
- while((tunnel_sock=accept_portal())==-1) sleep(4);
- ping_time=time(NULL);
- while(tunnel_sock!=-1){
- fd_set selector,errsel;
- struct connection *con=NULL;
- struct timeval alive_time;
-
- alive_time.tv_sec=ALIVE_TIME;
- alive_time.tv_usec=0;
- alive();
-
- /* We have to listen to the tunnel, the local port, and alle the
- current connections. */
- if(select(reset_selector(&selector,&errsel,con)+1,
- &selector,NULL,&errsel,&alive_time)){
- check_tunnel_connection(&selector,&errsel,con);
- check_connection_port(&selector,&errsel,con);
- check_local_connections(&selector,&errsel,con);
- }
- }
- sleep(2);
- }
- }
- <-->
- <++> tunnel/share.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <sys/utsname.h>
- #include <fcntl.h>
- #include <string.h>
- #include <signal.h>
- #include <errno.h>
- #include <netdb.h>
-
- #include "share.h"
-
- char tunnel_buf[MAXLEN*2]; /*Buffer to store the tunnel data in*/
- int tunnel_des; /*Destination socket */
- int tunnel_src; /*Source socket*/
- int tunnel_size; /*Size of the data currently in the buffer*/
- int tunnel_sock; /*The socket of the portal*/
- int tunnel_port; /*The port we wan't to run on*/
-
- extern FILE *log; /* Our log file*/
- extern int errno;
- struct connection *descriptors[DESC_MAX];
- struct connections connections; /*A linked list of our connections*/
-
- /*
- Packet header:
- ####################################/
- # Dest # Source# Data size # / data comes here
- ###################################\
- 1 byte 1 byte 2 bytes
-
- If the sestination field is zero, we are initiating a new connection
- If the source field we are dropping a connection
- If both the destination and the source is zero, it is a Myping packet.
- */
-
- void ctrlC(int sig)
- {
- fprintf(log,"Shutting down the hard way\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- exit(-1);
- }
-
-
- char *get_ip(char *host){
- struct hostent *remote;
- struct in_addr *in;
- remote=gethostbyname(host);
- if(remote==NULL){
- fprintf(log,"Hostinformation of remote machine '%s' not resolved,"\
- " reason:%s",host,strerror(errno));
- exit(-1);
- }
- in=(struct in_addr *)remote->h_addr_list[0];
- return(strdup(inet_ntoa(*in)));
- }
-
- int transmit_tunnel(char *data,int size,int source,int destination){
- int nleft=size+4,nwritten;
- fd_set selector,errsel;
- data[0]=(unsigned char)destination; /*Destination into header*/
- data[1]=(unsigned char)source; /*Source into header*/
- *((u_short *)&data[2])=htons(size); /*Size into header*/
- while(nleft>0){
- FD_ZERO(&errsel);
- FD_ZERO(&selector);
- FD_SET(tunnel_sock,&errsel);
- FD_SET(tunnel_sock,&selector);
- select(tunnel_sock+1,NULL,&selector,&errsel,NULL);
- if(FD_ISSET(tunnel_sock,&errsel)){
- printf("Big bug\n");
- }
- nwritten=write(tunnel_sock,data,nleft);
- if(nwritten==-1){
- fprintf(log,"Error writing to tunnel:%s\n",strerror(errno));
- tunnel_sock=-1;
- return(nwritten);
- }
- else if(nwritten==0){
- fprintf(log,"Error: Wrote zero bytes in transmit_tunnel\n");
- return(nwritten);
- }
- nleft-=nwritten;
- data+=nwritten;
- }
- return(size - nleft);
- }
-
- int receive_tunnel(){
- static int received=0;
- int n,left,got=0,quit=0,sofar=0;
- received++;
- while(sofar<4){
- quit=0;
- while(!quit){
- n=read(tunnel_sock,&tunnel_buf[sofar],4-sofar);
- if(n>0){quit=1;sofar+=n;}
- if(n<1){
- fprintf(log,"Connection terminated!\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- return(-1);
- }
- }
- }
- tunnel_des=tunnel_buf[0]; /*Fetch the destination*/
- tunnel_src=tunnel_buf[1]; /*Fetch the source*/
- tunnel_size=ntohs(*((u_short *)&tunnel_buf[2])); /*Fetch the size*/
- left=tunnel_size;
- while(left!=0){
- n=read(tunnel_sock,&tunnel_buf[got],left);
- if(n<0){
- fprintf(log,"Connection terminated in receive_tunnel!\n");
- shutdown(tunnel_sock,2);
- close(tunnel_sock);
- tunnel_sock=-1;
- return(-1);
- }
- got+=n;
- left-=n;
- }
- return(n);
- }
- void check_local_connections(fd_set *selector,fd_set *errsel,struct connection *con){
- /*Here we check each of the local connections for incoming date*/
- char buf[MAXLEN*2];
- int i,n;
- con=connections.head;
- for(i=0;i<connections.num&&con;i++,con=con->next){
- if(FD_ISSET(con->local_sock,errsel)){
- fprintf(log,"LLocal connection terminated\n");
- fprintf(log,"Removing connection to %s %d\n",con->host,con->port);
- if(con->remote_sock) transmit_tunnel(buf,0,0,con->remote_sock);
- removeconnection(con);
- break;
- }
- if(FD_ISSET(con->local_sock,selector)&&con->remote_sock){
- n=read(con->local_sock,&buf[4],MAXLEN);
- if(n<1){
- fprintf(log,"Local connection terminated\n");
- fprintf(log,"Removing connection to %s %d\n",con->host,con->port);
- transmit_tunnel(buf,0,0,con->remote_sock);
- removeconnection(con);
- break;
- }
- /*forward the data to the tunnel*/
- transmit_tunnel(buf,n,con->local_sock,con->remote_sock);
- }
- }
- }
-
- void ZERO(char * buf,int size){int i=0;while(i<size)buf[i++]=0;}
-
- int writen(int fd, char *ptr, int nbytes)
- {
- int nleft=nbytes,nwritten;
- while(nleft>0){
- nwritten=write(fd,ptr,nleft);
- if(nwritten<=0) return(nwritten);
- nleft-=nwritten;
- ptr+=nwritten;
- }
- return(nbytes - nleft);
- }
-
- int remote_connect(char *machine,int port)
- {
- int sock;
- struct sockaddr_in ser;
- ZERO((char *) &ser,sizeof(ser));
- ser.sin_family = AF_INET;
- ser.sin_addr.s_addr = inet_addr(machine);
- ser.sin_port = htons(port);
- sock=socket(AF_INET,SOCK_STREAM,0);
- if(sock==-1){perror("Error opening socket\n");return(-1);}
- if(connect(sock,(struct sockaddr *) &ser,sizeof(ser))==-1){
- fprintf(log,"Can't connect to server:%s\n",strerror(errno));
- return(-1);
- }
- return(sock);
- }
-
- void disconnect(struct connection *con,int sock1,int sock2){
- fprintf(log,"Closing link to: %s %d\n",con->host,con->port);
- shutdown(sock1,2);
- shutdown(sock2,2);
- close(sock1);
- close(sock2);
- close(con->local_sock);
- }
-
- void init_descriptors(){
- int i;
- for(i=0;i<DESC_MAX;i++){
- descriptors[i]=NULL;
- }
- }
-
- void removeconnection(struct connection *con){
- struct connection *c2,*c=connections.head;
- if(c==con){
- connections.head=c->next;
- descriptors[c->local_sock]=NULL;
- free(c->host);
- shutdown(c->local_sock,2);
- close(c->local_sock);
- free(c);
- connections.num--;
- return;
- }
- c2=c;
- c=c->next;
- while(c){
- if(c==con){
- /* connections.head=c2; */
- c2->next=c->next;
- descriptors[c->local_sock]=NULL;
- free(c->host);
- shutdown(c->local_sock,2);
- close(c->local_sock);
- free(c);
- connections.num--;
- return;
- }
- c2=c;
- c=c->next;
- }
- }
- <-->
- <++> tunnel/share.h
- /*********************/
- /* Structs & Defines */
- /*********************/
- #define MAX_HOSTNAME_SIZE 128
- #define MAXLEN 32768 /*Maximum length of our data*/
- #define ALIVE_TIME 60 /*Time to wait before sending a Myping*/
- #define DESC_MAX 128 /*Maximum number of descriptors used*/
- #define RETRY_TIME 60 /* Time to wait before we reconnect to portal*/
- #define max(a,b) ((a>b)?a:b)
- #define min(a,b) ((a<b)?a:b)
- #define AUTHOR "bishnu@hotmail.com"
-
- struct connections{
- int num;
- struct connection *head;
- };
-
- struct connection{
- struct connection *next;
- int port;
- int local_sock;
- int remote_sock;
- time_t time;
- char *host;
- };
-
-
- char *get_ip(char *host);
-
- void random_delay(int n);
- int transmit_tunnel(char *data,int size,int source,int destination);
- int receive_tunnel();
- void hostname(char *name);
- void ZERO(char * buf,int size);
- int writen(int fd, char *ptr, int nbytes);
- void ctrlC(int sig);
- void sleep_usec(int n);
- void nonblock(int s);
- int remote_connect(char *machine,int port);
- void disconnect(struct connection *con,int sock1,int sock2);
- void init_descriptors();
- int max_descriptor();
- void removeconnection(struct connection *con);
- void check_local_connections(fd_set *selector,fd_set *errsel,struct connection *con);
- <-->
-
-
- ----[ EOF
-
-