📄 idsocksserver.pas
字号:
begin
LSupportsAuth := false;
for a := 1 to byte( AThread.Connection.IOHandler.ReadChar ) do
begin
if byte( AThread.Connection.IOHandler.ReadChar ) = IdSocksAuthUsernamePassword then
begin
LSupportsAuth := true;
end;
end;
if not Socks5NeedsAuthentication then
begin
SendV5Response( AThread, IdSocksAuthNoAuthenticationRequired )
end
else
begin
if not LSupportsAuth then
begin
SendV5Response( AThread, IdSocksAuthNoAcceptableMethods ) ;
AThread.Connection.disconnect; // not sure the server has to disconnect
raise EIdSocksSvrNotSupported.create(RSSocksSvrNotSupported);
// exit; //exception
end
else
begin
SendV5Response( AThread, IdSocksAuthUsernamePassword ) ;
AThread.Connection.IOHandler.ReadChar; //subversion, we don't need it.
LUsername := AThread.Connection.IOHandler.ReadString( byte( AThread.Connection.IOHandler.readchar ) ) ;
LPassword := AThread.Connection.IOHandler.ReadString( byte( AThread.Connection.IOHandler.readchar ) ) ;
LValidLogin := false;
DoAuthenticate( TIdSocksServerContext( AThread ) , LUsername, LPassword, LValidLogin ) ;
if LValidLogin then
begin
AThread.Connection.IOHandler.Write(#1+chr(IdSocksLoginSuccess) );
end
else
begin
AThread.Connection.IOHandler.Write(#1+chr(IdSocksLoginFailure )) ;
AThread.Connection.disconnect;
raise EIdSocksSvrNotSupported.create(RSSocksSvrInvalidLogin);
//exit; //exception
end;
end;
end;
AThread.Connection.IOHandler.ReadChar; // socks version, should be 5
Acommand := byte( AThread.Connection.IOHandler.ReadChar ) ;
AThread.Connection.IOHandler.ReadChar; //reserved, should be 0
LTyp := byte( AThread.Connection.IOHandler.ReadChar ) ;
case LTyp of
1:
begin
Lline := AThread.Connection.IOHandler.ReadString( 6 ) ;
Ahost := inttostr( ord( Lline[1] ) ) + '.' + inttostr( ord( Lline[2] ) ) + '.' + inttostr( ord( Lline[3] ) ) + '.' + inttostr( ord( Lline[4] ) ) ;
Aport := ord( Lline[5] ) * 256 + ord( Lline[6] ) ;
end;
3:
begin
Ahost := AThread.Connection.IOHandler.ReadString( byte( AThread.Connection.IOHandler.readchar ) ) ;
Lline := AThread.Connection.IOHandler.ReadString( 2 ) ;
Aport := ord( Lline[1] ) * 256 + ord( Lline[2] ) ;
end;
4: // ip v6
begin
AThread.Connection.IOHandler.Readchar;// should be 18 (16 for host, and 2 for port)
Lline := AThread.Connection.IOHandler.ReadString( 18 ) ;
todo;
// Ahost:=GStack.TInAddrToString(lline[1],id_ipv6);
Aport := ord( Lline[17] ) * 256 + ord( Lline[18] ) ;
end;
else
raise EIdSocksSvrSocks5WrongATYP.Create( RSSocksSvrWrongATYP ) ;
end;
end;
procedure TIdCustomSocksServer.HandleConnectV4( AThread: TIdSocksServerContext; var ACommand: byte; var AUserId, AHost: string; var Aport: integer ) ;
var
Lline: string;
begin
Acommand := byte( AThread.Connection.IOHandler.ReadChar ) ;
Lline := AThread.Connection.IOHandler.ReadString( 2 ) ;
Aport := ord( Lline[1] ) * 256 + ord( Lline[2] ) ;
Lline := AThread.Connection.IOHandler.ReadString( 5 ) ;
Ahost := inttostr( ord( Lline[1] ) ) + '.' + inttostr( ord( Lline[2] ) ) + '.' + inttostr( ord( Lline[3] ) ) + '.' + inttostr( ord( Lline[4] ) ) ;
end;
function TIdCustomSocksServer.DoExecute( AThread: TIdContext ) : boolean;
var
LVersion: byte;
LCommand: byte;
LUserId: string;
LHost: string;
Lport: integer;
LSocksServerThread: TIdSocksServerContext absolute AThread;
begin
//just to keep the compiler happy
Result := True;
LVersion := byte( AThread.Connection.IOHandler.ReadChar ) ;
TIdSocksServerContext( AThread ) .SocksVersion := LVersion;
if not ( ( ( LVersion = 4 ) and AllowSocks4 ) or ( ( LVersion = 5 ) and AllowSocks5 ) ) then
raise EIdSocksSvrWrongSocksVer.Create( RSSocksSvrWrongSocksVersion ) ;
case LVersion of
4: HandleConnectV4( TIdSocksServerContext( AThread ) , LCommand, LUserId, LHost, Lport ) ;
5: HandleConnectV5( TIdSocksServerContext( AThread ) , LCommand, LUserId, LHost, Lport ) ;
end;
case LCommand of
1: CommandConnect( TIdSocksServerContext( AThread ) , LUserId, LHost, LPort ) ;
2: CommandBind( TIdSocksServerContext( AThread ) , LUserId, LHost, LPort ) ;
//3: //udp bind
else
raise EIdSocksSvrWrongSocksCmd.Create( RSSocksSvrWrongSocksCommand ) ;
end;
end;
procedure TIdSocksServer.CommandConnect( AThread: TIdSocksServerContext; AUserId, AHost: string; APort: integer ) ;
var
LIdtcpclient: tidtcpclient;
LAlowed: boolean;
begin
LAlowed := true;
DoBeforeConnectUser( AThread, AUserId, AHost, Aport, LAlowed ) ;
if not LAlowed then
begin
if AThread.SocksVersion = 4 then
begin
AThread.Connection.IOHandler.write( #0#2#0#1 + #0#0#0#0#0#0 )
end
else
begin
AThread.Connection.IOHandler.write( chr( AThread.SocksVersion ) + #2#0#1 + #0#0#0#0#0#0 ) ;
end;
raise EIdSocksSvrAccessDenied.Create( RSSocksSvrAccessDenied ) ;
end;
LIdtcpclient := nil;
try
LIdtcpclient := tidtcpclient.create( nil ) ;
LIdtcpclient.IOHandler:=TIdIOHandlerStack.Create(nil);
LIdtcpclient.port := Aport;
LIdtcpclient.host := Ahost;
try
if Length(MakeCanonicalIPv6Address(Ahost))>0 then
begin
todo;
// (LIdtcpclient.IOHandler as TIdIOHandlerStack).IPVersion:=Id_IPv6;
end;
LIdtcpclient.Connect;
if AThread.SocksVersion = 4 then
begin
AThread.Connection.IOHandler.write( #4#90 + #0#0#0#0#0#0 )
end
else
begin
AThread.Connection.IOHandler.write( chr( AThread.SocksVersion ) + #0#0#1 + #0#0#0#0#0#0 )
end;
except
if AThread.SocksVersion = 4 then
begin
AThread.Connection.IOHandler.write( #4#91#0#1 + #0#0#0#0#0#0 )
end
else
begin
AThread.Connection.IOHandler.write( chr( AThread.SocksVersion ) + #4#0#1 + #0#0#0#0#0#0 ) ;
raise;
end;
end;
TransferData( AThread.Connection, LIdtcpclient ) ;
LIdtcpclient.Disconnect;
AThread.Connection.Disconnect;
finally
if assigned(LIdtcpclient.IOHandler) then begin
LIdtcpclient.IOHandler.free;
LIdtcpclient.IOHandler:=nil;
end;
LIdtcpclient.free;
end;
end;
function ipStrToStr( ip: string ) : string;
var
a: integer;
begin
setlength( result, 4 ) ;
a := pos( '.', ip ) ;
result[1] := chr( strtoint( copy( ip, 1, a - 1 ) ) ) ;
ip := copy( ip, a + 1, maxint ) ;
a := pos( '.', ip ) ;
result[2] := chr( strtoint( copy( ip, 1, a - 1 ) ) ) ;
ip := copy( ip, a + 1, maxint ) ;
a := pos( '.', ip ) ;
result[3] := chr( strtoint( copy( ip, 1, a - 1 ) ) ) ;
ip := copy( ip, a + 1, maxint ) ;
result[4] := chr( strtoint( ip ) ) ;
end;
function PortToStr( const port: word ) : string;
begin
result := chr( Port div 256 ) + chr( Port mod 256 )
end;
procedure TIdSocksServer.CommandBind( AThread: TIdSocksServerContext; AUserId, AHost: string; APort: integer ) ;
var
LIdSimpleServer: TIdSimpleServer;
LAlowed: boolean;
begin
LAlowed := true;
DoBeforeBind( AThread, AUserId, AHost, Aport, LAlowed ) ;
if not LAlowed then
begin
if AThread.SocksVersion = 4 then
begin
AThread.Connection.IOHandler.write( #0#2#0#1 + #0#0#0#0#0#0 )
end
else
begin
AThread.Connection.IOHandler.write( #5#2#0#1 + #0#0#0#0#0#0 ) ;
end;
raise EIdSocksSvrAccessDenied.Create( RSSocksSvrAccessDenied ) ;
end;
LIdSimpleServer := nil;
try
LIdSimpleServer := TIdSimpleServer.create( nil ) ;
LIdSimpleServer.BeginListen;
if AThread.SocksVersion = 4 then
begin
AThread.Connection.IOHandler.write( #0 + #90 + PortToStr( LIdSimpleServer.Binding.Port ) + ipstrtostr( LIdSimpleServer.Binding.IP ) )
end
else
begin
AThread.Connection.IOHandler.write( chr( AThread.SocksVersion ) + #0#0#1 + ipstrtostr( LIdSimpleServer.Binding.IP ) + chr( LIdSimpleServer.Binding.Port div 256 ) + chr( LIdSimpleServer.Binding.Port mod 256 ) ) ;
end;
// while AThread.Connection.Connected do
// LIdSimpleServer.Listen(30000); // wait 30 secs
LIdSimpleServer.Listen;
// assert( LIdSimpleServer.binding.PeerIP = AHost ) ;
if not AThread.Connection.Connected then
begin
raise EIdSocksSvrUnexpectedClose.create( RSSocksSvrUnexpectedClose ) ;
end;
TransferData( AThread.Connection, LIdSimpleServer ) ;
LIdSimpleServer.Disconnect;
AThread.Connection.Disconnect;
finally
LIdSimpleServer.free;
end;
end;
procedure TIdEventSocksServer.CommandConnect( AThread: TIdSocksServerContext; AUserId, AHost: string; Aport: integer ) ;
begin
if assigned( foncommandconnect ) then
begin
foncommandconnect( AThread, AUserId, AHost, Aport ) ;
end;
end;
procedure TIdEventSocksServer.CommandBind( AThread: TIdSocksServerContext; AUserId, AHost: string; Aport: integer ) ;
begin
if assigned( foncommandbind ) then
begin
foncommandbind( AThread, AUserId, AHost, Aport ) ;
end;
end;
{ Constructor / Destructors }
procedure TIdCustomSocksServer.InitComponent;
begin
inherited;
FContextClass := TIdSocksServerContext;
DefaultPort := IdPORT_SOCKS;
AllowSocks4 := true;
AllowSocks5 := true;
Socks5NeedsAuthentication := false;
end;
destructor TIdCustomSocksServer.Destroy;
begin
inherited;
end;
{ TIdSocksServerContext }
constructor TIdSocksServerContext.Create;
begin
inherited;
FUser := '';
FPassword := '';
FSocksVersion := 0;
end;
destructor TIdSocksServerContext.Destroy;
begin
inherited;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -