📄 idsocks.pas
字号:
FreeAndNil(LIP);
end;
VLen := VLen + 16;
end
else
begin
// for now we stick with domain name, must ask Chad how to detect
// address type
if GStack.IsIP( AHost ) then
begin
VBuf[3] := $01; //IPv4 address
LIP := TIdIPAddress.MakeAddressObject(AHost);
try
if Assigned(LIP) then
begin
CopyTIdBytes(LIP.HToNBytes,0,VBuf,4,4);
end;
finally
FreeAndNil(LIP);
end;
VLen := 8;
end
else
begin
VBuf[3] := $3; // address type: IP V4 address: X'01' {Do not Localize}
// DOMAINNAME: X'03' {Do not Localize}
// IP V6 address: X'04' {Do not Localize}
// host name
VBuf[4] := Length(AHost);
VLen := 5;
if Length(AHost) > 0 then begin
CopyTIdBytes(ToBytes(AHost),0,VBuf,VLen,Length(AHost));
end;
VLen := VLen + Length(AHost);
end;
end;
// port
LtempPort := GStack.HostToNetwork(APort);
CopyTIdBytes(ToBytes(LtempPort),0,VBuf,VLen,2);
VLen := VLen + 2;
end;
procedure TIdSocksInfo.MakeSocks5Connection(AIOHandler: TIdIOHandler; const AHost: string; const APort: Integer);
var
pos: Integer;
LBuf: TIdBytes;
begin
AuthenticateSocks5Connection(AIOHandler);
SetLength(LBuf, 255);
MakeSocks5Request(AIOHandler, AHost, APort, $01, LBuf, Pos);
AIOHandler.WriteDirect(ToBytes(LBuf, pos)); // send the connection packet
try
AIOHandler.ReadBytes(LBuf, 5, False); // Socks server replies on connect, this is the first part
except
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
case LBuf[1] of
0: ;// success, do nothing
1: raise EIdSocksServerGeneralError.Create(RSSocksServerGeneralError);
2: raise EIdSocksServerPermissionError.Create(RSSocksServerPermissionError);
3: raise EIdSocksServerNetUnreachableError.Create(RSSocksServerNetUnreachableError);
4: raise EIdSocksServerHostUnreachableError.Create(RSSocksServerHostUnreachableError);
5: raise EIdSocksServerConnectionRefusedError.Create(RSSocksServerConnectionRefusedError);
6: raise EIdSocksServerTTLExpiredError.Create(RSSocksServerTTLExpiredError);
7: raise EIdSocksServerCommandError.Create(RSSocksServerCommandError);
8: raise EIdSocksServerAddressError.Create(RSSocksServerAddressError);
else
raise EIdSocksUnknownError.Create(RSSocksUnknownError);
end;
// type of destination address is domain name
case LBuf[3] of
// IP V4
1: pos := 4 + 2; // 4 is for address and 2 is for port length
// FQDN
3: pos := LBuf[4] + 2; // 2 is for port length
// IP V6
4: pos := 16 + 2; // 16 is for address and 2 is for port length
end;
try
// Socks server replies on connect, this is the second part
// RLebeau: why -1?
AIOHandler.ReadBytes(LBuf, pos-1, False); // just write it over the first part for now
except
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
end;
procedure TIdSocksInfo.MakeSocks4Bind(AIOHandler: TIdIOHandler; const AHost: string; const APort: Integer);
var
LResponse: TIdBytes;
LClient: TIdTcpClient;
begin
LClient := TIdTCPClient.Create(nil);
try
// SetLength(LResponse, 255);
SetLength(LResponse, 8);
TIdIOHandlerSocket(AIOHandler).TransparentProxy := nil;
LClient.IOHandler := AIOHandler;
LClient.Host := Host;
LClient.Port := Port;
LClient.Connect;
TIdIOHandlerSocket(AIOHandler).TransparentProxy := Self;
MakeSocks4Request(AIOHandler, AHost, APort, $02); //bind
AIOHandler.ReadBytes(LResponse, 2, False);
case LResponse[1] of // OpCode
90: ;// request granted, do nothing
91: raise EIdSocksRequestFailed.Create(RSSocksRequestFailed);
92: raise EIdSocksRequestServerFailed.Create(RSSocksRequestServerFailed);
93: raise EIdSocksRequestIdentFailed.Create(RSSocksRequestIdentFailed);
else raise EIdSocksUnknownError.Create(RSSocksUnknownError);
end;
try
// Socks server replies on connect, this is the second part
AIOHandler.ReadBytes(LResponse, 6, False); //overwrite the first part for now
TIdIOHandlerSocket(AIOHandler).Binding.SetBinding( IntToStr(LResponse[2])+'.'+IntToStr(LResponse[3])+'.'+IntToStr(LResponse[4])+'.'+IntToStr(LResponse[5]) , LResponse[0]*256+LResponse[1]);
except
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
finally
LClient.IOHandler := nil;
FreeAndNil(LClient);
end;
end;
procedure TIdSocksInfo.MakeConnection(AIOHandler: TIdIOHandler; const AHost: string; const APort: Integer);
begin
case Version of
svSocks4, svSocks4A: MakeSocks4Connection(AIOHandler, AHost, APort);
svSocks5: MakeSocks5Connection(AIOHandler, AHost, APort);
end;
end;
function TIdSocksInfo.GetEnabled: Boolean;
Begin
Result := Version in [svSocks4, svSocks4A, svSocks5];
End;//
procedure TIdSocksInfo.InitComponent;
begin
inherited;
Authentication := ID_SOCKS_AUTH;
Version := ID_SOCKS_VER;
Port := IdPORT_SOCKS;
FUDPSocksAssociation := TIdIOHandlerStack.Create;
end;
procedure TIdSocksInfo.AuthenticateSocks5Connection(
AIOHandler: TIdIOHandler);
var
pos: Integer;
LBuf: TIdBytes;
LRequestedAuthMethod,
LServerAuthMethod,
LUsernameLen,
LPasswordLen : Byte;
begin
SetLength(LBuf, 3);
// defined in rfc 1928
if Authentication = saNoAuthentication then begin
LBuf[2] := $0 // No authentication
end else begin
LBuf[2] := $2; // Username password authentication
end;
LRequestedAuthMethod := LBuf[2];
LBuf[0] := $5; // socks version
LBuf[1] := $1; // number of possible authentication methods
AIOHandler.WriteDirect(LBuf);
try
AIOHandler.ReadBytes(LBuf, 2, False); // Socks server sends the selected authentication method
except
On E: Exception do begin
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
end;
LServerAuthMethod := LBuf[1];
if (LServerAuthMethod <> LRequestedAuthMethod) or (LServerAuthMethod = $FF) then begin
raise EIdSocksAuthMethodError.Create(RSSocksAuthMethodError);
end;
// Authentication process
if Authentication = saUsernamePassword then begin
LUsernameLen := Length(Username);
LPasswordLen := Length(Password);
SetLength(LBuf, 3 + LUsernameLen + LPasswordLen);
LBuf[0] := 1; // version of subnegotiation
LBuf[1] := LUsernameLen;
pos := 2;
if LUsernameLen > 0 then begin
CopyTIdBytes(ToBytes(Username), 0, LBuf, pos, LUsernameLen);
pos := pos + LUsernameLen;
end;
LBuf[pos] := LPasswordLen;
pos := pos + 1;
if LPasswordLen > 0 then begin
CopyTIdBytes(ToBytes(Password), 0, LBuf, pos, LPasswordLen);
end;
AIOHandler.WriteDirect(LBuf); // send the username and password
try
AIOHandler.ReadBytes(LBuf, 2, False); // Socks server sends the authentication status
except
On E: Exception do begin
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
end;
if LBuf[1] <> $0 then begin
raise EIdSocksAuthError.Create(RSSocksAuthError);
end;
end;
end;
procedure TIdSocksInfo.MakeSocks5Bind(AIOHandler: TIdIOHandler; const AHost: string;
const APort: Integer);
var
Lpos: Integer;
LBuf: TIdBytes;
LClient:TIdTcpClient;
begin
LClient := TIdTCPClient.Create(nil);
try
SetLength(LBuf, 255);
TIdIOHandlerSocket(AIOHandler).TransparentProxy := nil;
LClient.IOHandler := AIOHandler;
LClient.Host := Host;
LClient.Port := Port;
LClient.Connect;
TIdIOHandlerSocket(AIOHandler).TransparentProxy := Self;
AuthenticateSocks5Connection(AIOHandler);
// Bind process
MakeSocks5Request(AIOHandler, AHost, APort, $02, LBuf, LPos); //bind request
//
AIOHandler.Write(ToBytes(LBuf, LPos)); // send the connection packet
try
AIOHandler.ReadBytes(LBuf, 4, False); // Socks server replies on connect, this is the first part
except
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
case LBuf[1] of
0: ;// success, do nothing
1: raise EIdSocksServerGeneralError.Create(RSSocksServerGeneralError);
2: raise EIdSocksServerPermissionError.Create(RSSocksServerPermissionError);
3: raise EIdSocksServerNetUnreachableError.Create(RSSocksServerNetUnreachableError);
4: raise EIdSocksServerHostUnreachableError.Create(RSSocksServerHostUnreachableError);
5: raise EIdSocksServerConnectionRefusedError.Create(RSSocksServerConnectionRefusedError);
6: raise EIdSocksServerTTLExpiredError.Create(RSSocksServerTTLExpiredError);
7: raise EIdSocksServerCommandError.Create(RSSocksServerCommandError);
8: raise EIdSocksServerAddressError.Create(RSSocksServerAddressError);
else
raise EIdSocksUnknownError.Create(RSSocksUnknownError);
end;
// type of destination address is domain name
case LBuf[3] of
// IP V4
1: Lpos := 4 + 2; // 4 is for address and 2 is for port length
// FQDN
3: Lpos := LBuf[4] + 2; // 2 is for port length
// IP V6
4: LPos := 16 + 2; // 16 is for address and 2 is for port length
end;
try
// Socks server replies on connect, this is the second part
AIOHandler.ReadBytes(LBuf, Lpos, False); //overwrite the first part for now
TIdIOHandlerSocket(AIOHandler).binding.SetBinding( IntToStr(LBuf[0])+'.'+IntToStr(LBuf[1])+'.'+IntToStr(LBuf[2])+'.'+IntToStr(LBuf[3]) ,LBuf[4]*256+LBuf[5]);
except
raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
end;
finally
LClient.IOHandler := nil;
FreeAndNil(LClient);
end;
end;
procedure TIdSocksInfo.Bind(AIOHandler: TIdIOHandler; const AHost: string;
const APort: Integer);
begin
case Version of
svSocks4, svSocks4A: MakeSocks4Bind(AIOHandler, AHost, APort);
svSocks5: MakeSocks5Bind(AIOHandler, AHost, APort);
end;
end;
function TIdSocksInfo.Listen(AIOHandler: TIdIOHandler;
const ATimeOut: integer): boolean;
begin
Result := False;
case Version of
svSocks4, svSocks4A: Result := MakeSocks4Listen(AIOHandler, ATimeOut);
svSocks5: Result := MakeSocks5Listen(AIOHandler, ATimeOut);
end;
end;
function TIdSocksInfo.MakeSocks5Listen(AIOHandler: TIdIOHandler;
const ATimeOut: integer): boolean;
var
Lpos: Integer;
LBuf: TIdBytes;
begin
SetLength(LBuf, 255);
Result := TIdIOHandlerSocket(AIOHandler).Binding.Readable(ATimeOut);
if Result then begin
AIOHandler.ReadBytes(LBuf, 4, False); // Socks server replies on connect, this is the first part
case LBuf[1] of
0: ;// success, do nothing
1: raise EIdSocksServerGeneralError.Create(RSSocksServerGeneralError);
2: raise EIdSocksServerPermissionError.Create(RSSocksServerPermissionError);
3: raise EIdSocksServerNetUnreachableError.Create(RSSocksServerNetUnreachableError);
4: raise EIdSocksServerHostUnreachableError.Create(RSSocksServerHostUnreachableError);
5: raise EIdSocksServerConnectionRefusedError.Create(RSSocksServerConnectionRefusedError);
6: raise EIdSocksServerTTLExpiredError.Create(RSSocksServerTTLExpiredError);
7: raise EIdSocksServerCommandError.Create(RSSocksServerCommandError);
8: raise EIdSocksServerAddressError.Create(RSSocksServerAddressError);
else
raise EIdSocksUnknownError.Create(RSSocksUnknownError);
end;
// type of destination address is domain name
case LBuf[3] of
// IP V4
1: Lpos := 4 + 2; // 4 is for address and 2 is for port length
// FQDN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -