Use Delphi to implement et5 proxy Programming

Source: Internet
Author: User
Tags socket error htons
Chen Jingtao
I. Preface

I often see a lot of people on the forum asking how to implement socket5 programming. Below I will write a few words about some superficial understandings of socket5. the article is divided into several series, including compiling of socket5 client and server. the article references some RFC documents and codes of socket5, which are not listed here. 2002.12.6, I would like to give this document to good friends Wang jiachun and Xiong Heng.

II. Implementation of the socket5 client based on the TCP protocol

The program works as follows: Your client program (send data) ------> socket5 Proxy Server (transit data) -----> remote target host (display data ). so you must have a socket5 proxy server software, strongly recommended Mr. Zhu yaokun write CCProxy, http://www.youngzsoft.com /.
Create a project, add four labels, five edits, one serversock control, one button, and one memo control. Add WinSock in uses. initialize each control during window initialization.

Procedure tform1.formcreate (Sender: tobject );
VaR
Tempwsadata: twsadata;
Begin
Label1.caption: = 'socks5 Proxy Server address ';
Edit1.text: = '2017. 0.0.1 ';
Label2.caption: = 'port of the SOCKS5 Proxy Server ';
Edit2.text: = '000000 ';
Label3.caption: = 'remote server address ';
Edit3.text: = '2017. 0.0.1 ';
Label4.caption: = 'remote server port ';
Edit4.text: = '000000 ';
Edit5.text: = 'Enter the character to be sent ';
Button1.caption: = 'test ';
Serversocket1.port: = 9999;
Serversocket1.active: = true;
Memo1.lines. Clear;
// Initialize Winsock
If (wsastartup (makeword (2, 0), tempwsadata) <> 0) then
Begin
Application. MessageBox ('program initialization failed! ', Pchar (application. Title), mb_iconinformation );
Application. Terminate;
End
Else
Memo1.lines. Add ('program initialization successful! ');
End;

Send data through the proxy server when you click button1

Procedure tform1.button1click (Sender: tobject );
VaR
Myclientsock: tsocket;
Socket5proxy: tsockaddr;
Targetsock: tsockaddr;
Mysocketbuf: array [0 .. 256] of byte;
Sendstrbuf: array [0 .. 1024*16] of char;
Pcharsocketaddr: pchar;
Re, I: integer;
Begin
Memo1.lines. Add ('----------------------------');
// 1: Create a socket
Myclientsock: = socket (af_inet, sock_stream, 0 );
If (myclientsock = invalid_socket) then
Begin
Memo1.lines. Add ('failed to create socket! ');
Exit;
End
Else
Memo1.lines. Add ('socket. Created successfully .');
// 2: connect to the socket5 Proxy Server
Zeromemory (@ socket5proxy, sizeof (socket5proxy ));
Socket5proxy. sin_family: = af_inet;
Getmem (pcharsocketaddr, length (edit1.text) + 1 );
Zeromemory (pcharsocketaddr, length (edit1.text) + 1 );
Strpcopy (pcharsocketaddr, edit1.text );
Socket5proxy. sin_addr.s_addr: = inet_addr (pcharsocketaddr );
Freemem (pcharsocketaddr );
Socket5proxy. sin_port: = htons (strtoint (edit2.text ));
Re: = connect (myclientsock, socket5proxy, sizeof (socket5proxy ));
If Re = socket_error then
Begin
Memo1.lines. Add ('Connection proxy server error. Error code: '+ inttostr (wsagetlasterror ()));
Closesocket (myclientsock );
Exit;
End
Else
Memo1.lines. Add ('proxy server connected successfully! ');
// 3: socket5 Protocol Verification and negotiation
Mysocketbuf [0]: = $05; mysocketbuf [1]: = $01; mysocketbuf [2]: = $00;
Re: = Send (myclientsock, mysocketbuf, 3, 0); // send a formatted message
If Re =-1 then
Begin
Memo1.lines. Add ('the server does not support socket5 proxy! ');
Closesocket (myclientsock );
Exit;
End;
Re: = Recv (myclientsock, mysocketbuf, 257,0); // receives the returned results
If Re <2 then
Begin
Memo1.lines. Add ('the server does not support socket5 proxy! ');
Closesocket (myclientsock );
Exit;
End;
If mysocketbuf [1] <> $00 then
Begin
Memo1.lines. Add ('the server requires authentication! ');
Closesocket (myclientsock );
Exit;
End;
Memo1.lines. Add ('negotiated with the socket5 proxy server! ');
// 4: Send remote host information and connect
Zeromemory (@ targetsock, sizeof (targetsock ));
Getmem (pcharsocketaddr, length (edit3.text) + 1 );
Zeromemory (pcharsocketaddr, length (edit3.text) + 1 );
Strpcopy (pcharsocketaddr, edit3.text );
Targetsock. sin_addr.s_addr: = inet_addr (pcharsocketaddr );
Targetsock. sin_port: = htons (strtoint (edit4.text ));
Targetsock. sin_family: = af_inet;
Mysocketbuf [0]: = $05; mysocketbuf [1]: = $01; mysocketbuf [2]: = $00; mysocketbuf [3]: = $01;
Copymemory (@ mysocketbuf [4], @ targetsock. sin_addr, 4 );
Copymemory (@ mysocketbuf [8], @ targetsock. sin_port, 2 );
Re: = Send (myclientsock, mysocketbuf, 10, 0 );
If Re =-1 then
Begin
Memo1.lines. Add ('failed to send remote host information! ');
Closesocket (myclientsock );
Exit;
End;
Re: = Recv (myclientsock, mysocketbuf );
If Re =-1 then
Begin
Memo1.lines. Add ('failed to receive returned information! ');
Closesocket (myclientsock );
Exit;
End;
If mysocketbuf [1] <> $00 then
Begin
Memo1.lines. Add ('failed to connect to the remote host! ');
Closesocket (myclientsock );
Exit;
End;
Memo1.lines. Add ('remote host connection successful! ');
// 5: send data
For I: = 0 to length (edit5.text)-1 do sendstrbuf [I]: = edit5.text [I + 1];
Re: = Send (myclientsock, sendstrbuf, strlen (sendstrbuf), 0 );
If Re =-1 then
Begin
Memo1.lines. Add ('failed to send data to the remote host! ');
Closesocket (myclientsock );
Exit;
End
Else
Memo1.lines. Add ('data is successfully sent to the remote host! ');
// 6: Disable socket
Memo1.lines. Add ('close socket! ');
Memo1.lines. Add ('----------------------------');
Closesocket (myclientsock );
End;

Put a serversocket control to receive and display information.

Procedure tform1.serversocket1clientread (Sender: tobject;
Socket: tcustomwinsocket );
VaR
Tempstr: string;
Begin
Tempstr: = socket. receivetext;
Application. MessageBox (pchar (tempstr), 'receive information', 0 );
End;

Do some work when the program exits.

Procedure tform1.formdestroy (Sender: tobject );
Begin
Wsacleanup (); // description of winsocket
End;
Run CCProxy to display the connection information as follows:

That is to say, as long as we shake hands and negotiate with the proxy server, we can directly regard the code server as transparent and non-existent, and regard the proxy server as a remote host. the above program is only for the absence of user authentication. if the proxy server needs verification, you only need to modify the handshake negotiation process. for more information, click here to download a csocksifiedsocket class (VC code ).

Iv. Principle of proxy server-a simple QQ data forwarding Program

The previous section describes some processes of et5 proxy programming. This section describes how the proxy server works with a simple data forwarding example, prepare for programming the socket5 proxy server in the next section.

What is a proxy server? Simply put, it is a data forwarding program. Its workflow is as follows: the proxy program a ---> Proxy Server ---> target server B. The proxy server sends the data sent by A to B and receives the data sent by B to. When a and B communicate with each other, they only deal with the proxy server.

There was an IP Phone proxy on the Internet, which was used to forward UDP data. For example, if you are using a LAN to access intenet, that is to say, you do not have a dynamic IP address. In this case, how can someone send data to your computer? One method is to use socket TCP programming. You connect to the other party first, but this connection requires the other party to have a dynamic IP address. Another method is to use the proxy. Of course, there are other methods. If we have time, we will mention them later. This example is implemented as follows: for example, if your IP address in the LAN is 192.168.0.77 and the dynamic IP address of the host that you connect to intenet is 202.98.26.74, run the proxy program on the host first, enter your IP address 192.168.0.77 in edit1, and the other party sends the data to port 6660 of host 202.98.26.74. Then, the host forwards the data to your computer. The program code is as follows:

Const maxpacket= 160;
VaR
Packetlen, playpackets: integer;
OK: integer = 0;
Mpackets: integer = 1;
Spackets: integer = 1;
Mbuffer: array [1 .. 160, 1 .. 2000] of char; // 8 seconds

Procedure tform1.formcreate (Sender: tobject );
Begin
Nmudp1.reportlevel: = status_basic;
Nmudp1.localport: = 6660; // local listening port
Nmudp1.remoteport: = 6661; // Remote Data receiving port
Playpackets: = 0;
End;

Procedure tform1.edit1change (Sender: tobject );
Begin
Nmudp1.remotehost: = edit1.text; // ip address of the remote host
End;

Procedure tform1.nmudp1datareceived (Sender: tcomponent; numberbytes: integer; fromip: string; port: integer );
VaR
Mdata: array [1 .. 2000] of char;
K: integer;
Begin
Packetlen: = numberbytes;
Nmudp1.readbuffer (mdata, numberbytes); // receives data
For K: = 1 to numberbytes do mbuffer [mpackets mod maxpackets + 1] [k]: = mdata [k];
Label2.caption: = 'packets: '+ inttostr (mpackets );
INC (mpackets );
Nmudp1.sendbuffer (mdata, numberbytes); // send data to the target host
End;

The above program implements one-to-one data transmission and one-way transmission. you can modify the settings to implement bidirectional data forwarding. the following describes a simple QQ data forwarding program. this example consists of two programs: the server and the client. The computer running the server must have a dynamic IP address.

The server uses a tserversocket and tnmudp. Serversocket1 receives the data sent from the client and sends it to the tengxun server through nmudp1. Then, nmudp1 receives the data from the tengxun server and sends it to the client through serversocket1. The Code is as follows:

Procedure tform1.formcreate (Sender: tobject );
Begin
Nmudp1.localport: = 4000; // local port: receives the message sent from tengxun Server
Nmudp1.remotehost: = '192. 104.129.20.'; // remote host: tengxun Server
Nmudp1.remoteport: = 8000; // remote port
Serversocket1.port: = 9000;
Serversocket1.active: = true;
End;

Procedure tform1.serversocket1clientconnect (Sender: tobject;
Socket: tcustomwinsocket );
Begin
Statusbar1.simpletext: = 'remote host' + socket. remoteaddress + 'the connection is established successfully! ';
End;

Procedure tform1.serversocket1clienterror (Sender: tobject;
Socket: tcustomwinsocket; errorevent: terrorevent;
VaR errorcode: integer );
Begin
Statusbar1.simpletext: = 'socket error! ';
Errorcode: = 0;
End;

Procedure tform1.serversocket1clientdisconnect (Sender: tobject;
Socket: tcustomwinsocket );
Begin
Statusbar1.simpletext: = 'remote host' + socket. remoteaddress + 'disconnect! ';
End;

Procedure tform1.serversocket1clientread (Sender: tobject;
Socket: tcustomwinsocket );
VaR
Len: integer;
Rec_bytes: integer;
Rec_buffer: array [0 .. 8191] of char;
Begin
Try
Len: = socket. cancelength;
Rec_bytes: = socket. receivebuf (rec_buffer, Len );
Nmudp1.sendbuffer (rec_buffer, rec_bytes );
Except
End;
End;

Procedure tform1.nmudp1datareceived (Sender: tcomponent;
Numberbytes: integer; fromip: string; port: integer );
VaR
C: array [1 .. 8192] of char;
I: integer;
Begin
Nmudp1.readbuffer (C, I); // The received characters are defined to C.
If I = 0 Then exit;
If serversocket1.socket. activeconnections> 0 then serversocket1.socket. Connections [0]. sendbuf (C, I );
End;

The client uses a tclientsocket and tnmudp. Nmudp1 receives QQ data and sends it to the server through clientsocket1. clientsocket1 receives the data from the server and forwards it to QQ through nmudp1. The Code is as follows:

Procedure tform1.formcreate (Sender: tobject );
Begin
Nmudp1.localport: = 8000; // open the port to connect to the local QQ. You can change it as needed.
Nmudp1.remotehost: = '192. 0.0.1 '; // It can be used to send a message to a local QQ and cannot be changed.
Nmudp1.remoteport: = 4000; // send information to the local QQ port. The port cannot be changed.
End;

Procedure tform1.button1click (Sender: tobject );
Begin
Clientsocket1.address: = edit1.text;
Clientsocket1.port: = 9000;
Clientsocket1.active: = true;
End;

Procedure tform1.clientsocket1connect (Sender: tobject;
Socket: tcustomwinsocket );
Begin
Statusbar1.simpletext: = 'successful connection ';
End;

Procedure tform1.clientsocket1disconnect (Sender: tobject;
Socket: tcustomwinsocket );
Begin
Statusbar1.simpletext: = 'disconnected ';
End;

Procedure tform1.clientsocket1error (Sender: tobject;
Socket: tcustomwinsocket; errorevent: terrorevent;
VaR errorcode: integer );
Begin
Statusbar1.simpletext: = 'socket error ';
Errorcode: = 0;
End;

Procedure tform1.nmudp1datareceived (Sender: tcomponent;
Numberbytes: integer; fromip: string; port: integer );
VaR
C: array [1 .. 8192] of char;
I: integer;
Begin
Nmudp1.readbuffer (C, I );
Try
If clientsocket1.active then clientsocket1.socket. sendbuf (C, I );
Except
End;
End;

Procedure tform1.clientsocket1read (Sender: tobject;
Socket: tcustomwinsocket );
VaR
Len: integer;
Rec_bytes: integer;
Rec_buffer: array [0 .. 8191] of char;
Begin
Try
Len: = socket. cancelength;
Rec_bytes: = socket. receivebuf (rec_buffer, Len );
Nmudp1.sendbuffer (rec_buffer, rec_bytes );
Except
End;
End;

The usage instructions and demo programs are available at http://tty.yyun.net/lovejingtao/ocx/qqproxyclient.htm. As mentioned above, no proxy server communication is required between a LAN and a LAN. That is
LAN computer A --- dialing host c -- intenet
LAN computer B --- dialing host d -- intenet
How can I implement communication between A and B without a proxy server? You can use the ing principle. Due to routing, C and D will automatically forward data to A and B. One of my friends has been successfully tested for a long time, unfortunately, this principle can only be used for UDP.

V. Design of socket5 Proxy Server

As mentioned above, you should easily design your own socket5 proxy server. Tip: Go back to Section 1. The client sends the login address and password to the server during verification. This will be left to everyone as a job. :) here is the answer.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.