A simple UDP proxy Program
As a supplement to <development process of a simple proxy program>
1. Why is this UDP program developed?
The network condition is shown in the preceding figure <development process of a simple proxy program>. Our socks proxy has permissions (I believe many companies
). When I write this program, I do not have the socks proxy permission, so I cannot access OICQ. This makes me feel
Inconvenient. Therefore, I decided to write a UDP proxy program to fulfill my desire to access OICQ. The principle is the same as above. Just in
The specific implementation is slightly different.
Let's take a look at the source code and explain it later. (This version is a fully functional version, so it provides a lot of features not provided by sp. C.
Yes .) The part mentioned above will not be explained one by one here.
Bytes -----------------------------------------------------------------------------------------
/*************************************** ************
Program: PU. c
Description: A smart UDP proxy
Author: Alan Chen (ariesram@may10.ca)
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 ("
Partitioned ed from outer:
", 23 );
/* Sizeof ("
Partitioned ed 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, "");
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 );
}
Bytes -----------------------------------------------------------------------------------------
Compile and run as described above.
However, you must note that UDP is not connected, so the specific implementation of the program is different.
Look at the program.
# 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 );
Ignore the above signal to run the program in the future.
# Ifndef _ debug
If (Fork ()! = 0)
Exit (0 );
Setsid ();
For (I = 256; I> = 0; I --)
# Endif
If it is not in debug mode, the program runs in the previous mode.
# Ifdef _ debug
For (I = 256; I> = 3; I --)
# Endif
Close (I );
Close the description.
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 is the IP address of the LAN on my machine. This program is only used by me, so it is not processed here
More flexible. :-)
Fd_listen = socket (pf_inet, sock_dgram, 0 );
If (fd_listen <0 ){
P_error ("socket1 error ");
Exit (1 );
}
The UDP socket description is created in this way.
Fcntl (fd_listen, f_setfl, o_nonblock );
Fcntl (fd_tran, f_setfl, o_nonblock );
Set the socket mode of the two listening ports to non-blocking.
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
}
For UDP, recvfrom and sendto are used. The client address when recvfrom is added to the program, which facilitates debugging.
. At the same time, there are some debugging information, such as the received string and client address.
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 ("
Partitioned ed from outer:
", 23 );
/* Sizeof ("
Partitioned ed 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
}
This section is the same. The difference is that the data is read from fd_tran and written back to fd_listen.
Description of two log functions.
Void
P_error (const char * err_msg)
{
File * FP;
# Ifdef _ debug
Printf ("% s
", Err_msg );
# Endif
Fp = fopen (errlog, "");
If (FP = NULL)
Return;
Fprintf (FP, "% s
", Err_msg );
Fclose (FP );
}
During debugging, the error message is output to the standard output.
When the status is not debug, output the error information to a hidden file under/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 );
}
Logs are written to the log file regardless of the debugging or non-debugging status.
Because the proxy server I use is not under my jurisdiction, I wrote the log file to/usr/tmp, which is relatively hidden.
And I have permissions. Haha. :-). During normal use, you can write logs to your specific directory. You only need to modify
# Define logfile "/usr/tmp/. PU. log"
# Define errlog "/usr/tmp/. PU. Err"
That's all.
Further improvement:
To make this program more universal, you can modify it so that it can set the service port number and Remote Server
IP address and port number. You can set the path of the log file.
If you have any questions, please contact me by email.
The source code is based on GNU. If you have changed the source code, you can also email me. :-)