一個簡易的UDP Proxy程序
作為<<一個簡易的proxy程序的開發過程>>的補充
1、為什麼開發這個UDP程序
網絡狀況如上文<<一個簡易的proxy程序的開發過程>>。我們的socks代理是有權限的(相信很多公司
都有這種情況存在)。寫這個程序的時候,我還沒有socks代理的權限,所以不能上OICQ。這讓我感到
很不方便。所以,我決定寫一個UDP的代理程序來實現我上OICQ的願望。原理同上文是一樣的。只是在
具體實現上略有所不同。
先看看源代碼,稍後再來解釋。(由於這個版本是一個完全功能版,所以提供了很多sp.c沒有提供的功
能。)上文中提到過的部分,這裡就不再次一一解釋了。
-----------------------------------------------------------------------------------------
/***************************************************
Program: pu.c
Description: a smart UDP proxy
Author: Alan Chen (
[email protected] )
Date: Dec 1, 2000
***************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#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);
}
-----------------------------------------------------------------------------------------
編譯,運行是同上文所述相同的。
但是,要注意UDP是沒有連接的,所以程序的具體實現方式有所不同。
來看程序。
#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_
}
-----------------------------------------------------------------------------------------
編譯,運行是同上文所述相同的。
但是,要注意UDP是沒有連接的,所以程序的具體實現方式有所不同。
來看程序。
#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_
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_