⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hts.c

📁 穿越防火墙技术代码
💻 C
字号:
/*hts.cCopyright (C) 1999 Lars Brinkhoff.  See COPYING for terms and conditions.hts is the server half of httptunnel.  httptunnel creates a virtualtwo-way data path tunneled in HTTP requests.*/#include <stdio.h>#include <stdlib.h>#include <unistd_.h>#include <signal.h>#include <sys/poll_.h>#include <sys/time.h>#include "common.h"typedef struct{  char *me;  char *device;  int port;  char *forward_host;  int forward_port;  size_t content_length;  char *pid_filename;  int strict_content_length;  int keep_alive;  int max_connection_age;} Arguments;int debug_level = 0;FILE *debug_file = NULL;static voidusage (FILE *f, const char *me){  fprintf (f,"Usage: %s [OPTION]... [PORT]\n""Listen for incoming httptunnel connections at PORT (default port is %d).\n""When a connection is made, I/O is redirected to the destination specified\n""by the --device or --forward-port switch.\n""\n""  -c, --content-length BYTES     use HTTP PUT requests of BYTES size\n""                                 (k, M, and G postfixes recognized)\n""  -d, --device DEVICE            use DEVICE for input and output\n"#ifdef DEBUG_MODE"  -D, --debug [LEVEL]            enable debug mode\n"#endif"  -F, --forward-port HOST:PORT   connect to PORT at HOST and use it for \n""                                 input and output\n""  -h, --help                     display this help and exit\n""  -k, --keep-alive SECONDS       send keepalive bytes every SECONDS seconds\n""                                 (default is %d)\n"#ifdef DEBUG_MODE"  -l, --logfile FILE             specify logfile for debug output\n"#endif"  -M, --max-connection-age SEC   maximum time a connection will stay\n""                                 open is SEC seconds (default is %d)\n""  -S, --strict-content-length    always write Content-Length bytes in requests\n""  -V, --version                  output version information and exit\n""  -p, --pid-file LOCATION        write a PID file to LOCATION\n""\n""Report bugs to %s.\n",	   me, DEFAULT_HOST_PORT, DEFAULT_KEEP_ALIVE,	   DEFAULT_MAX_CONNECTION_AGE, BUG_REPORT_EMAIL);}static voidparse_arguments (int argc, char **argv, Arguments *arg){  int c;  /* defaults */  arg->me = argv[0];  arg->port = DEFAULT_HOST_PORT;  arg->device = NULL;  arg->forward_host = NULL;  arg->forward_port = -1;  arg->content_length = DEFAULT_CONTENT_LENGTH;  arg->pid_filename = NULL;  arg->strict_content_length = FALSE;  arg->keep_alive = DEFAULT_KEEP_ALIVE;  arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME;    for (;;)    {      int option_index = 0;      static struct option long_options[] =      {	{ "help", no_argument, 0, 'h' },	{ "strict", no_argument, 0, 'S' },	{ "version", no_argument, 0, 'V' },#ifdef DEBUG_MODE	{ "debug", optional_argument, 0, 'D' },	{ "logfile", required_argument, 0, 'l' },#endif	{ "device", required_argument, 0, 'd' },	{ "pid-file", required_argument, 0, 'p' },	{ "keep-alive", required_argument, 0, 'k' },	{ "forward-port", required_argument, 0, 'F' },	{ "content-length", required_argument, 0, 'c' },	{ "max-connection-age", required_argument, 0, 'M' },	{ 0, 0, 0, 0 }      };      static const char *short_options = "c:d:F:hk:M:p:SV"#ifdef DEBUG_MODE	"D:l:"#endif	;      c = getopt_long (argc, argv, short_options,		       long_options, &option_index);      if (c == -1)	break;      switch (c)	{	case 0:	  printf ("option %s", long_options[option_index].name);	  if (optarg)	    printf (" with arg %s", optarg);	  printf ("\n");	  break;	  	case 'c':	  arg->content_length = atoi_with_postfix (optarg);	  break;	case 'd':	  arg->device = optarg;	  break;#ifdef DEBUG_MODE	case 'D':	  if (optarg)	    debug_level = atoi (optarg);	  else	    debug_level = 1;	  break;	case 'l':	  debug_file = fopen (optarg, "w");	  if (debug_file == NULL)	    {	      fprintf (stderr, "%s: couldn't open file %s for writing\n",		       arg->me, optarg);	      log_exit (1);	    }	  break;#endif /* DEBUG_MODE */	case 'F':	  name_and_port (optarg, &arg->forward_host, &arg->forward_port);	  if (arg->forward_port == -1)	    {	      fprintf (stderr, "%s: you must specify a port number.\n"		               "%s: try '%s --help' for help.\n",		       arg->me, arg->me, arg->me);	      exit (1);	    }	  break;	case 'h':	  usage (stdout, arg->me);	  exit (0);	case 'k':	  arg->keep_alive = atoi (optarg);	  break;	case 'M':	  arg->max_connection_age = atoi (optarg);	  break;	case 'S':	  arg->strict_content_length = TRUE;	  break;	case 'V':	  printf ("hts (%s) %s\n", PACKAGE, VERSION);	  exit (0);	case 'p':	  arg->pid_filename = optarg;	  break;	case '?':	  break;	default:	  printf ("?? getopt returned character code 0%o ??\n", c);	}    }  if (argc - 1 == optind)    arg->port = atoi (argv[optind]);  else if (argc - 1 > optind)    {      usage (stderr, arg->me);      exit (1);    }  if (arg->device == NULL && arg->forward_port == -1)    {      fprintf (stderr, "%s: one of --device or --forward-port must be used.\n"	               "%s: try '%s -help' for help.\n",	       arg->me, arg->me, arg->me);      exit (1);    }  if (arg->device != NULL && arg->forward_port != -1)    {      fprintf (stderr, "%s: --device can't be used together with "	                   "--forward-port.\n"	               "%s: try '%s --help' for help.\n",	       arg->me, arg->me, arg->me);      exit (1);    }  if (debug_level == 0 && debug_file != NULL)    {      fprintf (stderr, "%s: --logfile can't be used without debugging\n",	       arg->me);      exit (1);    }  if (((arg->device == NULL) == (arg->forward_port == -1)) ||      arg->port == -1 ||      ((arg->forward_host == NULL) != (arg->forward_port == -1)))    {      usage (stderr, arg->me);      exit (1);    }}intmain (int argc, char **argv){  int closed;  int fd = -1;  Arguments arg;  Tunnel *tunnel;  FILE *pid_file;  parse_arguments (argc, argv, &arg);  if (debug_level == 0 || debug_file != NULL)    daemon (0, 1);#ifdef DEBUG_MODE  if (debug_level != 0 && debug_file == NULL)    debug_file = stdout;#else  openlog ("hts", LOG_PID, LOG_DAEMON);#endif  log_notice ("hts (%s) %s started with arguments:", PACKAGE, VERSION);  log_notice ("  me = %s", arg.me);  log_notice ("  device = %s", arg.device ? arg.device : "(null)");  log_notice ("  port = %d", arg.port);  log_notice ("  forward_port = %d", arg.forward_port);  log_notice ("  forward_host = %s",	      arg.forward_host ? arg.forward_host : "(null)");  log_notice ("  content_length = %d", arg.content_length);  log_notice ("  debug_level = %d", debug_level);  log_notice ("  pid_filename = %s",	      arg.pid_filename ? arg.pid_filename : "(null)");  tunnel = tunnel_new_server (arg.port, arg.content_length);  if (tunnel == NULL)    {      log_error ("couldn't create tunnel", argv[0]);      log_exit (1);    }  if (tunnel_setopt (tunnel, "strict_content_length",		     &arg.strict_content_length) == -1)    log_debug ("tunnel_setopt strict_content_length error: %s",	       strerror (errno));  if (tunnel_setopt (tunnel, "keep_alive",		     &arg.keep_alive) == -1)    log_debug ("tunnel_setopt keep_alive error: %s", strerror (errno));  if (tunnel_setopt (tunnel, "max_connection_age",		     &arg.max_connection_age) == -1)    log_debug ("tunnel_setopt max_connection_age error: %s", strerror (errno));#ifdef DEBUG_MODE  signal (SIGPIPE, log_sigpipe);#else  signal (SIGPIPE, SIG_IGN);#endif  if(arg.pid_filename != NULL)    {      pid_file = fopen (arg.pid_filename, "w+");      if (pid_file == NULL)        {          fprintf (stderr, "Couldn't open pid file %s: %s\n",		   arg.pid_filename, strerror (errno));        }      else	{          fprintf (pid_file, "%d\n", (int)getpid ());	  if (fclose (pid_file))            {              fprintf (stderr, "Error closing pid file: %s\n", 		       strerror (errno));            }         }     }  for (;;)    {      time_t last_tunnel_write;      log_debug ("waiting for tunnel connection");      if (arg.device != NULL)	{	  fd = open_device (arg.device);	  log_debug ("open_device (\"%s\") = %d", arg.device, fd);	  if (fd == -1)	    {	      log_error ("couldn't open %s: %s",			 arg.device, strerror (errno));	      log_exit (1);	    }	}      if (tunnel_accept (tunnel) == -1)	{	  log_notice ("couldn't accept connection: %s", strerror (errno));	  continue;	}      log_notice ("connected to FIXME:hostname:port");      if (arg.forward_port != -1)	{	  struct sockaddr_in addr;	  if (set_address (&addr, arg.forward_host, arg.forward_port) == -1)	    {	      log_error ("couldn't forward port to %s:%d: %s\n",			 arg.forward_host, arg.forward_port, strerror (errno));	      log_exit (1);	    }	  fd = do_connect (&addr);	  log_debug ("do_connect (\"%s:%d\") = %d",		 arg.forward_host, arg.forward_port, fd);	  if (fd == -1)	    {	      log_error ("couldn't connect to %s:%d: %s\n",			 arg.forward_host, arg.forward_port, strerror (errno));	      log_exit (1);	    }	}      closed = FALSE;      time (&last_tunnel_write);      while (!closed)	{	  struct pollfd pollfd[2];	  int timeout;	  time_t t;	  int n;      	  pollfd[0].fd = fd;	  pollfd[0].events = POLLIN;	  pollfd[1].fd = tunnel_pollin_fd (tunnel);	  pollfd[1].events = POLLIN;	  time (&t);	  timeout = 1000 * (arg.keep_alive - (t - last_tunnel_write));	  if (timeout < 0)	    timeout = 0;	  log_annoying ("poll () ...");	  n = poll (pollfd, 2, timeout);	  log_annoying ("... = %d", n);	  if (n == -1)	    {	      log_error ("poll error: %s\n", strerror (errno));	      log_exit (1);	    }	  else if (n == 0)	    {	      log_verbose ("poll() timed out");	      tunnel_padding (tunnel, 1);	      time (&last_tunnel_write);	      continue;	    }	  log_annoying ("revents[0] = %x, revents[1] = %x, POLLIN = %x",			pollfd[0].revents, pollfd[1].revents, POLLIN);	  handle_input ("device or port", tunnel, fd, pollfd[0].revents,			handle_device_input, &closed);	  handle_input ("tunnel", tunnel, fd, pollfd[1].revents,			handle_tunnel_input, &closed);	  if (pollfd[0].revents & POLLIN)	    time (&last_tunnel_write);	}      log_debug ("closing tunnel");      close (fd);      tunnel_close (tunnel);      log_notice ("disconnected from FIXME:hostname:port");    }  log_debug ("destroying tunnel");  tunnel_destroy (tunnel);   log_exit (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -