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

📄 udp proxy.c

📁 《UDP Proxy程序》 我们的socks代理是有权限的(相信很多公司 都有这种情况存在)。写这个程序的时候
💻 C
字号:
/*************************************************** 
Program: UDP Proxy.c 
Description: a smart UDP proxy 
***************************************************/ 

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <sys/time.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <signal.h> 

#define MAX_ID_LEN 12 
#define LOGFILE "/usr/tmp/.pu.log" 
#define ERRLOG "/usr/tmp/.pu.err" 

void sig_int(int sig); 
void do_receive(int fd_tran); 
void p_error(const char * err_msg); 
void p_log(const char * buffer, int len); 

int 
main(int argc, char ** argv) 
{ 
int fd_listen, fd_tran; 
struct sockaddr_in sin, out; 
struct sockaddr_in r_in, r_out; 
struct sockaddr_in stmp; 
int port = 1250; 
int pid; 
char * ip; 
int i; 

fd_set fdset; 
char buffer[2048*2]; 
int data_len, alen; 
struct timeval val; 

#ifndef _DEBUG 
signal(SIGINT, SIG_IGN); 
#endif 
signal(SIGHUP, SIG_IGN); 
/* signal(SIGTERM, SIG_IGN); */ 
signal(SIGABRT, SIG_IGN); 
signal(SIGSTOP, SIG_IGN); 
signal(SIGCHLD, SIG_IGN); 

#ifndef _DEBUG 
if (fork() != 0) 
exit(0); 

setsid(); 

for (i = 256; i >= 0; i --) 
#endif 

#ifdef _DEBUG 
for (i = 256; i >= 3; i --) 
#endif 
close(i); 
chdir("/usr/tmp"); 

bzero(&sin, sizeof(sin)); 
sin.sin_family = AF_INET; 
sin.sin_port = htons(8000); 
sin.sin_addr.s_addr = INADDR_ANY; 

bzero(&out, sizeof(out)); 
out.sin_family = AF_INET; 
/* out.sin_port = htons(5000); */ 
out.sin_port = htons(4000); 
out.sin_addr.s_addr = INADDR_ANY; 

/* remote server */ 
bzero(&r_out, sizeof(r_out)); 
r_out.sin_family = AF_INET; 
r_out.sin_port = htons(8000); 
r_out.sin_addr.s_addr = inet_addr("202.96.170.164"); 

/* remote client */ 
bzero(&r_in, sizeof(r_in)); 
r_in.sin_family = AF_INET; 
r_in.sin_port = htons(4000); 
r_in.sin_addr.s_addr = inet_addr("192.168.103.97"); 

fd_listen = socket(PF_INET, SOCK_DGRAM, 0); 
if (fd_listen < 0) { 
p_error("socket1 error"); 
exit(1); 
} 

fd_tran = socket(PF_INET, SOCK_DGRAM, 0); 
if (fd_tran < 0) { 
p_error("socket2 error"); 
exit(1); 
} 

if (bind(fd_listen, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 
p_error("bind error1: "); 
exit(1); 
} 

if (bind(fd_tran, (struct sockaddr *)&out, sizeof(out)) < 0) { 
p_error("bind error2: "); 
exit(1); 
} 

fcntl(fd_listen, F_SETFL, O_NONBLOCK); 
fcntl(fd_tran, F_SETFL, O_NONBLOCK); 

while (1) { 
FD_ZERO(&fdset); 
FD_SET(fd_tran, &fdset); 
FD_SET(fd_listen, &fdset); 
val.tv_sec = 1; 
val.tv_usec = 0; 

if (select(fd_tran + 1, &fdset, NULL, NULL, &val) < 0) { 
p_error("select error: "); 
continue; 
} 
if (FD_ISSET(fd_listen, &fdset)) { 
alen = sizeof(r_in); 
data_len = recvfrom (fd_listen, buffer, sizeof(buffer), 0, 
(struct sockaddr *)&r_in, &alen); 
if (data_len <= 0) { 
p_error("socket closed by remote client"); 
close(fd_listen); 
close(fd_tran); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_in.sin_addr.s_addr); 
printf("received from %s , socket id: %d 
", ip, fd_listen); 
p_log(" 

received from inner: 
", 23); 
/* sizeof(" 

received from inner: 
"); */ 
p_log(buffer, data_len); 
#endif 

if (sendto(fd_tran, (char *)buffer, data_len, 0, 
(struct sockaddr *)&r_out, sizeof(r_out)) <=0 ) { 
p_error("cann't send to remote server"); 
close(fd_tran); 
close(fd_listen); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_out.sin_addr.s_addr); 
printf("send to %s 
", ip); 
#endif 

} 
else if (FD_ISSET(fd_tran, &fdset)) { 
alen = sizeof(stmp); 
data_len = recvfrom (fd_tran, buffer, sizeof(buffer), 0, 
(struct sockaddr *)&stmp, &alen); 
if (data_len <= 0) { 
p_error("socket closed by remote server"); 
close(fd_listen); 
close(fd_tran); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(stmp.sin_addr.s_addr); 
printf("received from %s , socket id: %d 
", ip, fd_tran); 
p_log(" 

received from outer: 
", 23); 
/* sizeof(" 

received from outer: 
"); */ 
p_log(buffer, data_len); 
#endif 

if (sendto(fd_listen, (char *)buffer, data_len, 0, 
(struct sockaddr *)&r_in, 
sizeof(r_in)) <=0 ) { 
p_error("cann't send to remote server"); 
close(fd_tran); 
close(fd_listen); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_in.sin_addr.s_addr); 
printf("send to %s 
", ip); 
#endif 

} 
} 
return 0; 

} 

void 
sig_int(int sig) 
{ 
signal(SIGINT, sig_int); 
exit(1); 
} 

void 
p_error(const char * err_msg) 
{ 
FILE * fp; 

#ifdef _DEBUG 
printf("%s 
", err_msg); 
#endif 

fp = fopen(ERRLOG, "a"); 
if (fp == NULL) 
return; 
fprintf(fp, "%s 
", err_msg); 
fclose(fp); 
} 

void 
p_log(const char * buffer, int len) 
{ 
FILE * fp; 

fp = fopen(LOGFILE, "ab"); 
if (fp == NULL) 
return; 
fwrite(buffer, len, 1, fp); 
fclose(fp); 

} 


#ifndef _DEBUG 
signal(SIGINT, SIG_IGN); 
#endif 
signal(SIGHUP, SIG_IGN); 
/* signal(SIGTERM, SIG_IGN); */ 
signal(SIGABRT, SIG_IGN); 
signal(SIGSTOP, SIG_IGN); 
signal(SIGCHLD, SIG_IGN); 
/*忽略上述信号,使程序以后台方式运行。*/ 
#ifndef _DEBUG 
if (fork() != 0) 
exit(0); 

setsid(); 

for (i = 256; i >= 0; i --) 
#endif 
/*如果不是DEBUG方式,程序以前台方式运行。*/ 
#ifdef _DEBUG 
for (i = 256; i >= 3; i --) 
#endif 
close(i); 
/*关闭描述字。*/ 
bzero(&r_in, sizeof(r_in)); 
r_in.sin_family = AF_INET; 
r_in.sin_port = htons(4000); 
r_in.sin_addr.s_addr = inet_addr("192.168.103.97"); 
/*192.168.103.97 是我机器的局域网IP地址。由于这个程序只是给我一个人使用的,所以没有在这上面处理 得更灵活一些。:-) */
fd_listen = socket(PF_INET, SOCK_DGRAM, 0); 
if (fd_listen < 0) { 
p_error("socket1 error"); 
exit(1); 
} 
/*UDP的socket描述字是这样子建立的。*/ 
fcntl(fd_listen, F_SETFL, O_NONBLOCK); 
fcntl(fd_tran, F_SETFL, O_NONBLOCK); 
/*将这两个监听端口的socket方式设置为非阻塞的。*/ 

if (FD_ISSET(fd_listen, &fdset)) { 
alen = sizeof(r_in); 
data_len = recvfrom (fd_listen, buffer, sizeof(buffer), 0, 
(struct sockaddr *)&r_in, &alen); 
if (data_len <= 0) { 
p_error("socket closed by remote client"); 
close(fd_listen); 
close(fd_tran); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_in.sin_addr.s_addr); 
printf("received from %s , socket id: %d 
", ip, fd_listen); 
p_log(" 

received from inner: 
", 23); 
/* sizeof(" 

received from inner: 
"); */ 
p_log(buffer, data_len); 
#endif 

if (sendto(fd_tran, (char *)buffer, data_len, 0, 
(struct sockaddr *)&r_out, sizeof(r_out)) <=0 ) { 
p_error("cann't send to remote server"); 
close(fd_tran); 
close(fd_listen); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_out.sin_addr.s_addr); 
printf("send to %s 
", ip); 
#endif 

} 
/*对于UDP来说,用的是recvfrom和sendto. 在程序中同时加入了recvfrom时的客户端地址,便于在调试的 
时候来检查。同时,这里面也有一些调试的信息,比如,输出接收到的字符串,客户端地址等等。*/ 
else if (FD_ISSET(fd_tran, &fdset)) { 
alen = sizeof(stmp); 
data_len = recvfrom (fd_tran, buffer, sizeof(buffer), 0, 
(struct sockaddr *)&stmp, &alen); 
if (data_len <= 0) { 
p_error("socket closed by remote server"); 
close(fd_listen); 
close(fd_tran); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(stmp.sin_addr.s_addr); 
printf("received from %s , socket id: %d 
", ip, fd_tran); 
p_log(" 

received from outer: 
", 23); 
/* sizeof(" 

received from outer: 
"); */ 
p_log(buffer, data_len); 
#endif 

if (sendto(fd_listen, (char *)buffer, data_len, 0, 
(struct sockaddr *)&r_in, 
sizeof(r_in)) <=0 ) { 
p_error("cann't send to remote server"); 
close(fd_tran); 
close(fd_listen); 
exit(0); 
} 
#ifdef _DEBUG 
ip = inet_ntoa(r_in.sin_addr.s_addr); 
printf("send to %s 
", ip); 
#endif 

} 
/*这一段是一样的。所不同的是,从fd_tran中读出来写回到fd_listen中去。*/ 

/*两个日志函数的说明。*/ 
void 
p_error(const char * err_msg) 
{ 
FILE * fp; 

#ifdef _DEBUG 
printf("%s 
", err_msg); 
#endif 

fp = fopen(ERRLOG, "a"); 
if (fp == NULL) 
return; 
fprintf(fp, "%s 
", err_msg); 
fclose(fp); 
} 
/*调试的时候,将错误信息输出到标准输出上。 
非调试状态的时候,将错误信息输出到/usr/tmp/下的一个隐藏文件中。*/ 
void 
p_log(const char * buffer, int len) 
{ 
FILE * fp; 

fp = fopen(LOGFILE, "ab"); 
if (fp == NULL) 
return; 
fwrite(buffer, len, 1, fp); 
fclose(fp); 

} 
/*不论调试还是非调试状态,都把日志写到日志文件中。 
由于我所使用的代理服务器不是我所管辖,所以我把日志文件写到了/usr/tmp下,这是一个相对来说比较隐蔽 的位置而且我也有权限。呵呵。:-). 正常使用时,可以把日志写到你的特定目录下。这只要修改 
#define LOGFILE "/usr/tmp/.pu.log" 
#define ERRLOG "/usr/tmp/.pu.err" 
就行了。 

进一步的改进: 
为了让这个程序更加有通用性,可以修改一下,让他在命令行中能够设置服务端口号,远程服务器的 iP地址和端口号,能够设置日志文件的路径。*/ 

⌨️ 快捷键说明

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