telnet proxy


Ce programme est un telnet_proxy.
Vous n'avez pas toujours un acces direct à toutes les machines sur internet mais vous pouvez faire un telnet sur le proxy de votre entreprise pour ensuite vous connecter sur la machine et un port donné.
Ce programme permet de faire les choses de façon transparente.

Vous lancez le programme en indiquant le port sur lequel il doit ecouter, l'adresse du proxy, et la machine sur laquelle vous voulez vous connecter.
Par exemple si vous voulez acceder aux mails de votre compte pop externe à l'entreprise ( le compte pop de votre fournisseur d'accés à la maison ), il vous suffit de lancer : telnet_proxy -l 110 -t pop.monIsp.fr -T 110 -p proxy_de_lentreprise -P 23
Dans le code, vous devez définir les messages envoyés par le proxy:
  • PROMPT : défini le prompt du proxy pour passer des commandes
  • CONN_PROMPT_OK : message envoyé par le proxy pour dire que la connexion est établie
  • CONN_CLOSED : message envoyé par le proxy pour dire que la connexion est coupée

#include <arpa/telnet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define DEBUG 0
#define TRACKING 0

#define CONN_OK_W_DATA 2
#define CONN_OK        1
#define CONN_FAILED    0

#define PROMPT   "tn-gw->"
#define CONN_PROMPT_OK "Connected to"
#define CONN_CLOSED "Remote server has closed connection"

#define PACKET_SIZE  1024
#define MAX(a,b) (a<b?b:a)
#define FSET(a,b,c)  (FD_ISSET(a,c)?a:b)
#define NFSET(a,b,c) (FD_ISSET(a,c)?b:a)


int writen(int fd, char *ptr, int n);
int readn(int fd, char *ptr, int n);
int forward(int fin, int fout);
int  telnet_init(void);

unsigned short server_port = 12346;

char *proxy_name = "proxy";
unsigned short proxy_port = 23;

char *target_host = "target";
unsigned short target_port = 80;
struct sockaddr_in serverSock, clientSock, proxySock;
int fserver, ftarget, fcurrent, fproxy;

void usage ( void ) {

  printf ( "Usage: telnet_proxy [OPTION]\n"
           "open a tunnel via a proxy server\n\n"
           "  -?     \t this help\n"
           "  -l port\t local port to listen ( default 12345 )\n"
           "  -p host\t proxy hostname ( default proxy )\n"
           "  -P port\t proxy port ( default 23 )\n"
           "  -t host\t target hostname ( default target )\n"
           "  -T port\t target port ( default 80 )\n");
}

int main(int argc , char *argv[])
{
  int ret, len, c;
  struct hostent *proxyHostEnt;        /* description du host serveur */
  unsigned long hostAddr;                       /* addr du serveur */
  fd_set fdsr;
  long flags;


  while ( ( c = getopt(argc,argv,"?l:p:P:t:T:") ) != -1 ) {
    switch ( c ) {
      case 'l' : server_port = atoi(optarg);   break;
      case 'P' : proxy_port  = atoi(optarg);   break;
      case 'T' : target_port = atoi(optarg);   break;
      case 'p' : proxy_name  = strdup(optarg); break;
      case 't' : target_host = strdup(optarg); break;
      case '?' :
      default  :
        usage();
        return 0;
    }
  }

  printf("listen port:%d, proxy: %s:%d, target: %s:%d\n",server_port,
         proxy_name,proxy_port,target_host,target_port);


  fserver = socket(AF_INET, SOCK_STREAM, 0);
  if (fserver < 0) {
    perror("socket");
    return -1;
  } else if ( DEBUG ) {
    printf("server : %d\n",fserver);
  }
  serverSock.sin_family = AF_INET;
  serverSock.sin_addr.s_addr = INADDR_ANY;
  serverSock.sin_port = htons(server_port);
  if (bind(fserver, (struct sockaddr *) &serverSock, sizeof(struct sockaddr_in))
      < 0) {
    perror("bind");
    return -1;
  }
  if (listen(fserver, 0) < 0) {
    perror("listen");
    return -1;
  }

  for (;;) {
    FD_ZERO(&fdsr);
    FD_SET(fserver, &fdsr);

    ret = select(fserver + 1, &fdsr, 0, 0, 0);
    if (ret <= 0) {
      close(fserver);
    }
    fcurrent = accept(fserver, (struct sockaddr *) &clientSock, &len);
    fcntl(fcurrent, F_GETFL, &flags);
    flags |= O_NONBLOCK;
    fcntl(fcurrent, F_SETFL, &flags);

    if (DEBUG) {
      printf("current : %d\n", fcurrent);
    }

    bzero(&proxySock, sizeof(proxySock));
    hostAddr = inet_addr(proxy_name);
    if ((long) hostAddr != (long) -1)
      bcopy(&hostAddr, &proxySock.sin_addr, sizeof(hostAddr));
    else {      /* si on a donne un nom  */

      proxyHostEnt = gethostbyname(proxy_name);
      if (proxyHostEnt == NULL) {
        printf("ca chie gethost\n");
        exit(0);
      }
      bcopy(proxyHostEnt->h_addr, &proxySock.sin_addr,proxyHostEnt->h_length);
    }
    proxySock.sin_port = htons(proxy_port); /* host to network port */
    proxySock.sin_family = AF_INET; /* AF_*** : INET=internet */
    if ((fproxy = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      printf("ca chie creation socket client\n");
      exit(0);
    }
    if (connect (fproxy, (struct sockaddr *) &proxySock,sizeof(proxySock))<0) {
      printf("ca chie demande de connection\n");
      exit(0);
    }
    if (DEBUG) {
      printf("proxy : %d\n", fproxy);
    }
    if ( telnet_init() == CONN_OK ) {
      fcntl(fproxy, F_GETFL, &flags);
      flags |= O_NONBLOCK;
      fcntl(fproxy, F_SETFL, &flags);

      do {
        FD_ZERO(&fdsr);
        FD_SET(fcurrent, &fdsr);
        FD_SET(fproxy, &fdsr);
        if (DEBUG) printf("now wait ... \n");
        ret = select(MAX(fcurrent, fproxy) + 1, &fdsr, 0, 0, 0);
        if (ret <= 0) {
          if (DEBUG) printf("on ferme\n");
          close(fproxy);
          close(fcurrent);
          break;
        }
        len = 0;
        if ( FD_ISSET(fcurrent,&fdsr) )
          len = forward(fcurrent, fproxy);
        if ( FD_ISSET(fproxy,&fdsr) )
          len = forward(fproxy, fcurrent);
      } while (len);
      if (DEBUG) printf("on ferme\n");
      close(fcurrent);
      close(fproxy);
    } else {
      if (DEBUG) printf("on ferme\n");
      close(fcurrent);
      close(fproxy);
    }
  }

  return 0;
}


int get_prompt(int fd)
{
  int nl, nr, n=PACKET_SIZE;
  char deb_ptr[PACKET_SIZE];
  char *ptr = deb_ptr;

  nl = n;
  while (nl > 0) {
    nr = read(fd, ptr, nl);
    if (nr < 0) return nr;    /* error */
    else if (nr == 0) break;
    nl -= nr;
    ptr += nr;
    if (strstr(ptr-10,PROMPT)) return CONN_OK;
  }
  return CONN_FAILED;
}

int get_connected(int fd, char *deb_ptr, int n)
{
  int nl, nr;
  char *ptr = deb_ptr, *ptr2;
  char conn_prompt_ok_string[PACKET_SIZE];

  sprintf(conn_prompt_ok_string,"%s %s.\r\n",CONN_PROMPT_OK, target_host);

  nl = n;
  while (nl > 0) {
    nr = read(fd, ptr, nl);
    ptr[nr] = 0x00;
    if ( DEBUG ) printf("->%s<-\n", ptr);
    if (nr < 0) return nr;    /* error */
    else if (nr == 0) break;
    nl -= nr;
    ptr += nr;
    if ( ptr2 = strstr(deb_ptr,conn_prompt_ok_string) ) {
      ptr2 += strlen(conn_prompt_ok_string);
      if ( DEBUG ) printf("->%s<-",ptr2);
      writen(fcurrent, ptr2, strlen(ptr2));
      return CONN_OK;
    }
    if ( strstr(ptr-10,PROMPT) ) return CONN_FAILED;
  }
  return CONN_FAILED;
}


int  telnet_init(void)
{
  char option[] = { IAC, WILL, TELOPT_BINARY };
  int szo = sizeof(option);
  unsigned char buf[PACKET_SIZE + 1];
  int n , ret;

  /* force binary on the socket */
  if (DEBUG) printf("sending options ...");
  writen(fproxy, option, szo);
  option[1] = DO;
  writen(fproxy, option, szo);

  if (DEBUG) printf("reading header ...");
  n = get_prompt(fproxy);
  if (DEBUG) printf("connected proxy !!\n");

  sprintf(buf,"connect %s %d\n", target_host, target_port);
  writen(fproxy, buf, strlen(buf));
  ret = get_connected(fproxy, buf, PACKET_SIZE);
  if (DEBUG) printf("connected target ? %s\n",(ret==CONN_OK?"oui":"non"));

  return ret;
}


int writen(int fd, char *ptr, int n)
{

int nl, nw;
        nl = n;
        while ( nl > 0 ) {
                nw = write(fd, ptr, nl);
                if ( nw <= 0 )
                        return nw;     /*error*/
                nl -= nw;
                ptr += nw;
        }
        return (n-nl);
}


int readn(int fd, char *ptr, int n){

int nl, nr;
        nl = n;
        while ( nl > 0 ) {
                nr = read(fd,ptr,nl);
                if (nr < 0 ) {
                  if ( nr == -1 )  {
                    *ptr = 0x00;
                    return (n-nl);
                  }
                        return nr;     /*error*/
                } else {
                        if ( nr == 0 )
                                break;
                }
                nl -= nr;
                ptr += nr;
        }
        *ptr = 0x00;
        return (n-nl);
}


int forward(int fin, int fout)
{
  int total=0, len=0, i = 0;
  char buffer[PACKET_SIZE + 1];
  char *ptr;

  if (DEBUG) printf ( "^[[31m%d -> %d\n^[[30m",fin,fout);

  do {
    len = readn(fin, buffer, PACKET_SIZE);
    buffer[len] = 0x00;
    if ( ptr = strstr(buffer, CONN_CLOSED) ) {
      if ( DEBUG ) printf("----> '%s' found\n",CONN_CLOSED);
      *ptr=0x00;
    }
    if ( ( len = strlen(buffer) ) != 0 )  {
      if (TRACKING) printf("%d-%d->%s<--\n",i++,len,buffer);
      writen(fout, buffer, len);
      total += len;
    }
  } while (len == PACKET_SIZE);
  return total;
}