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

📄 sockd.c

📁 Linux下的socks的程序源程序,用于socks的代理服务
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <pwd.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/signal.h>#include <syslog.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/ioctl.h>#include <netdb.h>#include <stdio.h>#include <ctype.h>#include <errno.h>#if (defined(sun) && !defined(SOLARIS)) || defined(sgi)#include <strings.h>#else#include <string.h>#endif#include "socks.h"#include <fcntl.h>#if defined(AIX)#include <sys/mode.h>#endif#if defined(sgi) && defined(SYSTYPE_SVR4)#include <sys/stat.h>#endif#include "ident.h"#define IDENTD_TIMEOUT 15 /* 15 seconds */static int	use_identd = 0;#define STREQ(a, b)	(strcmp(a, b) == 0)char socks_cmd[] = "connect";static char *sockd_conf = SOCKD_CONF;static char server_version[] = "4.1";static unsigned short socks_port;static unsigned short socks_client_port;extern char	*socks_porttoserv();extern char	*socks_saddrtoname();extern	void	socks_mkargs();extern	int socks_GetAddr();extern	int socks_GetQuad();extern	long	socks_GetPort();extern	int	socks_check_user();#define NAMELEN	128char	socks_src_name[NAMELEN], socks_src_user[NAMELEN];char	socks_real_user[NAMELEN];char	socks_dst_name[NAMELEN], socks_dst_serv[NAMELEN];static char log_msg[1024];#ifdef DEBUGstatic char buf[1024];#endifstatic struct config *cfPtr, **cfEntries = NULL;static int cfNtries = 0;#ifdef MULTIHOMED_SERVERstatic struct config *rtPtr, **rtEntries = NULL;static int rtNtries = 0;#endif /* MULTIHOMED_SERVER */#define BAD_ID_STR	"#BAD_ID:"#define NO_IDENTD_STR	"#NO_IDENTD:"#ifdef NOT_THROUGH_INETDstatic char bad_id_cmd[1024];static char no_identd_cmd[1024];void rereadConfig();void reapChild();/* void killChildren(); */void dumpconf();#endif /* #ifdef NOT_THROUGH_INETD */static u_int32	from_in = 0L, from_out = 0L;/***  Current version for response messages*/int		Version = 0;void die(){	syslog(LOG_HIGH, "timed-out -- %s", log_msg);	exit(1);}#ifdef FOR_PSmain(argc, argv, envp)int	argc;char	*argv[];char	*envp[];#else /* FOR_PS not defined */main(argc, argv)int	argc;char	*argv[];#endif /* #ifdef FOR_PS */{	char			c;	int			inp, in, out, nindex=0;	int			i, n, len = sizeof(struct sockaddr_in);	struct sockaddr_in	sin, from, dstsin;	int			fromlen = sizeof(struct sockaddr_in);	Socks_t			dst;	int			one = 1;	struct servent	*sp;	int	permit;#ifdef NOT_THROUGH_INETD/*	int pid;*/	pid_t pid;	struct passwd *pw;	sigset_t mask;	int devnull;	char pidstr[32];	int pidf, pidlen;#endif#if defined(FOR_PS) && !defined(SYSV)#define MAXUSERENVIRON 100	char *UserEnviron[MAXUSERENVIRON+1];    /* saved user environment */	extern char **environ;	char ps_buf[1024];	char **Argv = NULL;   /* pointer to argument vector */	char *LastArgv = NULL;        /* end of argv */#define newstr(s)    strcpy(malloc(strlen(s) + 1), s)  	for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)		UserEnviron[i] = newstr(envp[i]);	UserEnviron[i] = NULL;	environ = UserEnviron;	/*	**  Save start and extent of argv for setproctitle.	*/	Argv = argv;	if (i > 0)		LastArgv = envp[i - 1] + strlen(envp[i - 1]);	else		LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);#endif /* FOR_PS && !SYSV *//* if started by root, change the uid to nobody. */#ifdef NOT_THROUGH_INETD/*	if (getuid() == 0) {		if((pw = getpwnam("nobody")) == (struct passwd *)0) {			fprintf(stderr, "Terminated: User nobody not in password file\n");			exit(1);		}		if (setuid(pw->pw_uid) < 0) {			fprintf(stderr, "Terminated: Can't change uid to nobody\n");			exit(1);		}	}*/#endif /* ifdef NOT_THROUGH_INETD */	socks_port = htons(SOCKS_DEF_PORT);	bzero((char *)&sin, sizeof(sin));	bzero((char *)&from, sizeof(from));	bzero((char *)&dstsin, sizeof(dstsin));	if (argc >= 2) {		if (strcmp(argv[1],"-ver") == 0) {#ifdef MULTIHOMED_SERVER# ifdef NOT_THROUGH_INETD		printf(" CSTC multi-homed, stand-alone SOCKS proxy server version %s.\n", CSTC_RELEASE);# else		printf(" CSTC multi-homed, inetd-controlled SOCKS proxy server version %s.\n", CSTC_RELEASE);# endif#else /* MULTIHOMED_SERVER not defined */# ifdef NOT_THROUGH_INETD		printf(" CSTC single-homed, stand-alone SOCKS proxy server version %s.\n", CSTC_RELEASE);# else		printf(" CSTC single-homed, inetd-controlled SOCKS proxy server version %s.\n", CSTC_RELEASE);# endif#endif /* #ifdef MULTIHOMED_SERVER */#if defined(SUPPORT_RCMD)		printf(" Supports clients that use Rrcmd().\n");#else /* SUPPORT_RCMD not defined */		printf(" Does not support clients that use Rrcmd().\n");#endif /* #if defined(SUPPORT_RCMD) */		exit(1);		} else if (strcmp(argv[1], "-i") == 0)			use_identd = 1;		else if (strcmp(argv[1], "-I") == 0)			use_identd = 2; /* strict use of identd */		else ;	}	strcpy(socks_real_user,"unknown");	if ((sp = getservbyname("socks", "tcp")) != NULL)		socks_port = sp->s_port;#ifndef LOG_DAEMON	(void) openlog("sockd", LOG_PID);#else	(void) openlog("sockd", LOG_PID, SYSLOG_FAC);#endif#ifdef NOT_THROUGH_INETD    if ((pid = fork()) == -1) {		syslog(LOG_HIGH, "starup could not fork (%m)!");        exit(1);	}    if (pid)        exit(0);	/* we are backgrounded now */	syslog(LOG_LOW, "sockd server starting");    (void) setsid();    (void) chdir("/");	devnull = open("/dev/null", O_RDWR, 0);	if (devnull != -1) {		(void) dup2(devnull, 0);		(void) dup2(devnull, 1);		(void) dup2(devnull, 2);		if (devnull > 2)			(void) close(devnull);    }	/* read the configuration (for non-inetd, once for all future children) */	if (!readConfig()) {		syslog(LOG_HIGH, "Terminate");		exit(1);	}#ifdef MULTIHOMED_SERVER	/* read the route configuration (for non-inetd, once for all future children) */	if (!readRoute()) {		syslog(LOG_HIGH, "Terminate");		exit(1);	}#endif /* MULTIHOMED_SERVER */		sigemptyset(&mask);	sigaddset(&mask, SIGCHLD);	sigprocmask(SIG_UNBLOCK, &mask, NULL);	/* signal(SIGTERM, killChildren); */	signal(SIGHUP, rereadConfig);	signal(SIGCHLD, reapChild);	signal(SIGUSR1, dumpconf);	inp  = socket(AF_INET, SOCK_STREAM, 0);	sin.sin_family = AF_INET;	sin.sin_port = socks_port;	sin.sin_addr.s_addr = htonl(INADDR_ANY);	if (bind(inp, &sin, sizeof(sin)) < 0) {		syslog(LOG_HIGH, "error -- main bind() %m");		exit(1);	}	if (listen(inp, MAX_CLIENTS) < 0) {		syslog(LOG_HIGH, "error -- main listen() %m");		exit(1);	}/* Put our process id in /tmp/sockd.pid */#define PID_FILE "/tmp/sockd.pid"	if ((pidf = open(PID_FILE, O_RDWR|O_CREAT|O_TRUNC,		S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {		syslog(LOG_HIGH, "Cannot create/access %s", PID_FILE);	} else {		sprintf(pidstr, "%d\n", getpid());		if (write(pidf, pidstr, strlen(pidstr)) < 0)			syslog(LOG_HIGH, "Cannot write to /%s", PID_FILE);		close(pidf);	}	/* parent stays within this loop */	for (;;) {		int pid;			if ((in = accept(inp, &sin, &len)) < 0) {			if (errno == EINTR) continue;	/* caught SIGCHLD */			syslog(LOG_HIGH, "error -- main accept() %m");			exit(1);		}	    		if ((pid = fork()) == 0) break;	/* child */		if (pid == -1) syslog(LOG_HIGH, "fork failed - %m");	    /* parent stays in loop */		close(in);	}	/* in child now */	signal(SIGHUP, SIG_IGN);	signal(SIGCHLD, SIG_IGN);	signal(SIGTERM, SIG_DFL);	closelog();	close(inp);#ifndef LOG_DAEMON	(void) openlog("sockd", LOG_PID);#else	(void) openlog("sockd", LOG_PID, SYSLOG_FAC);#endif	/* LOG_DAEMON */#else	in = dup(0);#endif /* NOT_THROUGH_INETD */	if (getpeername(in, (struct sockaddr *)&from, &fromlen) < 0) {		syslog(LOG_HIGH, "error -- unable to get client address.");		exit(1);	}	socks_client_port = ntohs(from.sin_port);#ifdef DEBUG	syslog(LOG_LOW, "socks_client_port=%u", socks_client_port);#endif /* #ifdef DEBUG */	socks_saddrtoname(&from.sin_addr, socks_src_name, sizeof(socks_src_name));	if (socks_GetDst(in, &dst) < 0) {		syslog(LOG_HIGH, "Error in socks_GetDst: %m; from host %s", socks_src_name);		exit(1);	}	if (dst.version != SOCKS_VERSION) {		syslog(LOG_HIGH, "error -- wrong version (0x%2x) from host %s.",			dst.version, socks_src_name);		exit(1);	}	if (dst.cmd != SOCKS_CONNECT && dst.cmd != SOCKS_BIND) {		syslog(LOG_HIGH, "error -- undefined command (0x%2x) from host %s",			dst.cmd, socks_src_name);		exit(1);	}	dstsin.sin_family      = AF_INET;	dstsin.sin_addr.s_addr = dst.host;	dstsin.sin_port        = dst.port;	while (read(in, &c, 1) == 1)		if (c == '\0')			break;		else {			if (nindex < sizeof(socks_src_user) - 1)			socks_src_user[nindex++] = c;		}	socks_src_user[nindex] = '\0';	if (dstsin.sin_addr.s_addr == 0)		strcpy(socks_dst_name, "Unspecified.Host");	else		socks_saddrtoname(&dstsin.sin_addr, socks_dst_name, sizeof(socks_dst_name));	socks_porttoserv(dstsin.sin_port, socks_dst_serv, sizeof(socks_dst_serv));	permit = Validate(&from, &dstsin, in);	if (dst.cmd == SOCKS_CONNECT) {		strcpy(socks_cmd, "connect");		sprintf(log_msg, "Connect from %s(%s)@%s to %s (%s)",			socks_src_user, socks_real_user, socks_src_name, socks_dst_name, socks_dst_serv);#ifdef FOR_PS		sprintf(ps_buf, "%s: %s(c) to %s",			socks_src_user, socks_dst_serv, socks_dst_name);		setproctitle(ps_buf, Argv, LastArgv);#endif /* #ifdef FOR_PS */	} else {		strcpy(socks_cmd, "bind");		sprintf(log_msg, "Bind from %s(%s)@%s for %s",			socks_src_user, socks_real_user, socks_src_name, socks_dst_name);#ifdef FOR_PS		sprintf(ps_buf, "%s: %s(b) to %s",			socks_src_user, socks_dst_serv, socks_dst_name);		setproctitle(ps_buf, Argv, LastArgv);#endif /* #ifdef FOR_PS */	}	if (permit == 1) 		;	else if (permit == 0) {		syslog(LOG_LOW, "refused -- %s", log_msg);		exit(1);	} else if (permit == -1) {		syslog(LOG_LOW, "cannot connect to identd on %s", socks_src_name);	} else if (permit == -2) {		syslog(LOG_LOW, "refused -- %s", log_msg);		syslog(LOG_LOW, "cannot connect to identd on %s", socks_src_name);		dst.cmd = SOCKS_NO_IDENTD;		socks_SendDst(in, &dst);		exit(1);	} else if (permit == -3) {		syslog(LOG_LOW, "refused -- %s", log_msg);		syslog(LOG_LOW, "*Alert*: real user is %s, not %s", socks_real_user, socks_src_user);		dst.cmd = SOCKS_BAD_ID;		socks_SendDst(in, &dst);		exit(1);	} else {		syslog(LOG_HIGH, "refused -- %s", log_msg);		syslog(LOG_HIGH, "Unexpected result from Validate");		exit(1);	}#ifdef DEBUG	strcpy(buf, inet_ntoa(from.sin_addr));	syslog(LOG_LOW,"USER:%s,  SRC:%s,  DST:%s, PORT:%u",		socks_src_user, buf, inet_ntoa(dstsin.sin_addr),		ntohs(dstsin.sin_port));#endif /* DEBUG */	/*	**  Kill a connecting off if bind or connect takes too	**    long to complete	*/	signal(SIGALRM, die);	/*alarm(60*5);*/		/* 5 minutes */	alarm(60*2);	if (dst.cmd == SOCKS_CONNECT) {		DoConnect(in, &dst);	}	if (dst.cmd == SOCKS_BIND) {		DoNewBind(in, &dst);	}}socks_fail(str, in, ndst)char	*str;int	in;Socks_t	*ndst;{	syslog(LOG_LOW, "failed -- %s.  Error code: %s %m", log_msg, str);	ndst->cmd = SOCKS_FAIL;	socks_SendDst(in, ndst);	exit(1);}/*** Actually connect a socket to the outside world,*/DoConnect(in, dst)int	in;Socks_t	*dst;{	int			out;	struct sockaddr_in	sin;	Socks_t			ndst;	int	outport = IPPORT_RESERVED - 1;	int	turnon = 1;	bzero((char *)&sin, sizeof(sin));#if defined(SO_OOBINLINE)	setsockopt(in, SOL_SOCKET, SO_OOBINLINE, &turnon, sizeof(turnon));#endif#if defined(SUPPORT_RCMD)#ifdef DEBUG	syslog(LOG_LOW, "DoConnect(): client port=%u", socks_client_port);#endif /* #ifdef DEBUG */	if ((socks_client_port < IPPORT_RESERVED) && 		(socks_client_port >= IPPORT_RESERVED/2)) {		if ((out = rresvport(&outport)) < 0)			socks_fail("rresvport()", in, &ndst);#if !defined(SCO) && !defined(ISC)#if defined(hpux)		ioctl(out, FIOSSAIOOWN, getpid());#else /* hpux not defined */		fcntl(out, F_SETOWN, getpid());#endif /* #if defined(hpux) */#endif /* #if !defined(SCO) && !defined(ISC) */	} else if ((out = socket(AF_INET, SOCK_STREAM, 0)) < 0)		socks_fail("socket()", in, &ndst);

⌨️ 快捷键说明

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