⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idsocks.pas

📁 photo.163.com 相册下载器 多线程下载
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      3: Lpos := LBuf[4] + 2; // 2 is for port length
      // IP V6  - 4:
    else
      Lpos := 16 + 2; // 16 is for address and 2 is for port length
    end;
    // Socks server replies on connect, this is the second part
    AIOHandler.ReadBytes(LBuf, Lpos, False);      // just write it over the first part for now
    TIdIOHandlerSocket(AIOHandler).Binding.SetPeer(IntToStr(LBuf[0])+'.'+IntToStr(LBuf[1])+'.'+IntToStr(LBuf[2])+'.'+IntToStr(LBuf[3]),LBuf[4]*256+LBuf[5]);
  end;
end;

function TIdSocksInfo.MakeSocks4Listen(AIOHandler: TIdIOHandler;
  const ATimeOut: integer): boolean;
var
  LBuf: TIdBytes;
begin
  SetLength(LBuf, 6);
  Result := TIdIOHandlerSocket(AIOHandler).Binding.Readable(ATimeOut);
  if Result then begin
    AIOHandler.ReadBytes(LBuf, 2, False);    // Socks server replies on connect, this is the first part

    case LBuf[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;

    // Socks server replies on connect, this is the second part
    AIOHandler.ReadBytes(LBuf, 6, False);      // just write it over the first part for now
    TIdIOHandlerSocket(AIOHandler).Binding.SetPeer(IntToStr(LBuf[2])+'.'+IntToStr(LBuf[3])+'.'+IntToStr(LBuf[4])+'.'+IntToStr(LBuf[5]) , LBuf[0]*256+LBuf[1]);
  end;
end;

procedure TIdSocksInfo.CloseSocks5UDPAssociation;
begin
  if Assigned(FUDPSocksAssociation) then
  begin
    FUDPSocksAssociation.Close;
  end;
end;

procedure TIdSocksInfo.MakeSocks5UDPAssociation(AHandle: TIdSocketHandle);
var
  Lpos: Integer;
  LBuf: TIdBytes;

begin
  FUDPSocksAssociation.Host := Self.Host;
  FUDPSocksAssociation.Port := Self.Port;
  FUDPSocksAssociation.Open;
  try
    SetLength(LBuf, 255);
    AuthenticateSocks5Connection(FUDPSocksAssociation);
    // Associate process
    //For SOCKS5 Associate, the IP address and port is the client's IP address and port which may
    //not be known
    if AHandle.IPVersion = IdGlobal.Id_IPv4 then
    begin
      MakeSocks5Request(FUDPSocksAssociation, '0.0.0.0', 0, $03, LBuf, LPos); //associate request
    end
    else
    begin
      MakeSocks5Request(FUDPSocksAssociation, '::0', 0, $03, LBuf, LPos); //associate request
    end;
    //
    FUDPSocksAssociation.Write(ToBytes(LBuf, LPos)); // send the connection packet
    try
      FUDPSocksAssociation.ReadBytes(LBuf, 2, False);    // Socks server replies on connect, this is the first part )VER and RSP
    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;
    FUDPSocksAssociation.ReadBytes(LBuf, 2, False); //Now get RSVD and ATYPE feilds
    // type of destination address is domain name
    case LBuf[1] 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
      FUDPSocksAssociation.ReadBytes(LBuf, Lpos, False); //overwrite the first part for now
      AHandle.SetPeer( (FUDPSocksAssociation as TIdIOHandlerStack).Binding.PeerIP ,LBuf[4]*256+LBuf[5]);  //IntToStr(LBuf[0])+'.'+IntToStr(LBuf[1])+'.'+IntToStr(LBuf[2])+'.'+IntToStr(LBuf[3])
      AHandle.Connect;
    except
      raise EIdSocksServerRespondError.Create(RSSocksServerRespondError);
    end;
  except
    on E: Exception do
    begin
      FUDPSocksAssociation.Close;
      raise;
    end;
  end;
end;

procedure TIdSocksInfo.CloseUDP(AHandle: TIdSocketHandle);
begin
  case Version of
    svSocks4, svSocks4A: raise EIdSocksUDPNotSupportedBySOCKSVersion.Create(RSSocksUDPNotSupported);
    svSocks5: CloseSocks5UDPAssociation;
  end;
end;

procedure TIdSocksInfo.OpenUDP(AHandle: TIdSocketHandle;
  const AHost: string=''; const APort: Integer=0);
begin
  case Version of
    svSocks4, svSocks4A: raise EIdSocksUDPNotSupportedBySOCKSVersion.Create(RSSocksUDPNotSupported);
    svSocks5: MakeSocks5UDPAssociation(AHandle);
  end;
end;

function TIdSocksInfo.DisasmUDPReplyPacket(const APacket : TIdBytes;
  var VHost : String; var VPort : Integer): TIdBytes;
{


      +----+------+------+----------+----------+----------+
      |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
      +----+------+------+----------+----------+----------+
      | 2  |  1   |  1   | Variable |    2     | Variable |
      +----+------+------+----------+----------+----------+
        01    2      3
     The fields in the UDP request header are:

          o  RSV  Reserved X'0000'
          o  FRAG    Current fragment number
          o  ATYP    address type of following addresses:
             o  IP V4 address: X'01'
             o  DOMAINNAME: X'03'
             o  IP V6 address: X'04'
          o  DST.ADDR       desired destination address
          o  DST.PORT       desired destination port
          o  DATA     user data
}
var LLen : Integer;
//  LIP : TIdIPAddress;
  LIP6 : TIdIPv6Address;
  LtempPort : Word;
  LHost : TIdBytes;
  i : Integer;
begin
  if Length(APacket)<5 then
  begin
    Exit;
  end;
    // type of destination address is domain name
    case APacket[3] of
      // IP V4
      1: begin
           LLen := 4 + 4; //4 IPv4 address len, 4- 2 reserved, 1 frag, 1 atype
           VHost := IntToStr(APacket[4])+'.'+IntToStr(APacket[5])+'.'+IntToStr(APacket[6])+'.'+IntToStr(APacket[7]);

         end;
      // FQDN
      3: begin
           LLen := APacket[4] +4; // 2 is for port length, 4 - 2 reserved, 1 frag, 1 atype
           if Length(APacket)< (5+LLen) then
           begin
             Exit;
           end;
           SetLength(LHost,APacket[4]);
           CopyTIdBytes(APacket,5,LHost,0,APacket[4]);
           VHost := BytesToString(LHost);
         end;
      // IP V6  - 4:
    else
      LLen := 16 + 4; // 16 is for address, 2 is for port length,4 - 2 reserved, 1 frag, 1 atype
      SetLength(LHost,16);
      CopyTIdBytes(APacket,5,LHost,0,16);
      LIP6 := BytesToIPv6(LHost);
      for i := 0 to 7 do
      begin
        LIP6[i] := GStack.NetworkToHost(LIP6[i]);
      end;
      VHost := IPv6AddressToStr(LIP6);
    end;
    LtempPort := APacket[LLen]*256+ APacket[LLen+1];
    VPort := LtempPort;
  LLen := LLen + 2;
  SetLength(Result,Length(APacket)-LLen);
  CopyTIdBytes(APacket,LLen,Result,0,Length(APacket)-LLen);
end;

function TIdSocksInfo.MakeUDPRequestPacket(const AData: TIdBytes;
      const AHost : String; const APort : Integer) : TIdBytes;

{


      +----+------+------+----------+----------+----------+
      |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
      +----+------+------+----------+----------+----------+
      | 2  |  1   |  1   | Variable |    2     | Variable |
      +----+------+------+----------+----------+----------+
        01    2      3
     The fields in the UDP request header are:

          o  RSV  Reserved X'0000'
          o  FRAG    Current fragment number
          o  ATYP    address type of following addresses:
             o  IP V4 address: X'01'
             o  DOMAINNAME: X'03'
             o  IP V6 address: X'04'
          o  DST.ADDR       desired destination address
          o  DST.PORT       desired destination port
          o  DATA     user data
}
var LLen : Integer;
  LIP : TIdIPAddress;
  LtempPort : Word;
begin
  SetLength(Result,1024);
  Result[0] := 0;
  Result[1] := 0;
  Result[2] := 0; //no fragmentation - too lazy to implement it
  if (length(MakeCanonicalIPv6Address(AHost))>0) then begin
    Result[3] := $4;   // address type: IP V4 address: X'01'    {Do not Localize}
                           //               DOMAINNAME:    X'03'    {Do not Localize}
                           //               IP V6 address: X'04'    {Do not Localize}

    Result[4] :=16; // 16 bytes for the ip
    LLen := 5;
    LIP := TIdIPAddress.MakeAddressObject(AHost);
    try
      if Assigned(LIP) then
      begin
        CopyTIdBytes(LIP.HToNBytes,0,Result,4,16);
      end;
    finally
      FreeAndNil(LIP);
    end;
    LLen := LLen + 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
      Result[3] := $01;  //IPv4 address
      Result[4] :=4; // 4 bytes for the ip
      LIP := TIdIPAddress.MakeAddressObject(AHost);
      try
        if Assigned(LIP) then
        begin
          CopyTIdBytes(LIP.HToNBytes,0,Result,4,4);
        end;
      finally
        FreeAndNil(LIP);
      end;
      LLen := 8;
    end
    else
    begin
      Result[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
      Result[4] := Length(AHost);
      LLen := 5;
      if Length(AHost) > 0 then begin
        CopyTIdBytes(ToBytes(AHost),0,Result,LLen,Length(AHost));
      end;
      LLen := LLen + Length(AHost);
    end;

  end;

  // port
  LtempPort := APort;  //done this way to avoid a range check error
  LtempPort := GStack.HostToNetwork(LtempPort);
  CopyTIdBytes(ToBytes(LtempPort),0,Result,LLen,2);
  LLen := LLen + 2;
  //now do the rest of the packet
  SetLength(Result,LLen + Length(AData));
  CopyTIdBytes(AData,0,Result,LLen,Length(AData));
end;

function TIdSocksInfo.RecvFromUDP(AHandle: TIdSocketHandle;
 var ABuffer : TIdBytes;
  var VPeerIP: string; var VPeerPort: integer;
  AMSec: Integer = IdTimeoutDefault): integer;
var LBuf : TIdBytes;

begin
  case Version of
    svSocks4, svSocks4A: raise EIdSocksUDPNotSupportedBySOCKSVersion.Create(RSSocksUDPNotSupported);
  end;
  SetLength(LBuf,Length(ABuffer)+200);

  if not AHandle.Readable(AMSec) then begin
    Result := 0;
    VPeerIP := '';    {Do not Localize}
    VPeerPort := 0;
    Exit;
  end;
  Result := AHandle.RecvFrom(LBuf,VPeerIP, VPeerPort);
  SetLength(LBuf,Result);
  LBuf := DisasmUDPReplyPacket(LBuf, VPeerIP, VPeerPort);
  Result := Length(LBuf);
  IdGlobal.CopyTIdBytes(LBuf,0,ABuffer,0,Result);
end;

procedure TIdSocksInfo.SendToUDP(AHandle: TIdSocketHandle;
      AHost: string; const APort: Integer; const ABuffer : TIdBytes);
var LBuf : TIdBytes;
begin
  case Version of
    svSocks4, svSocks4A: raise EIdSocksUDPNotSupportedBySOCKSVersion.Create(RSSocksUDPNotSupported);
  end;
  LBuf := MakeUDPRequestPacket(ABuffer, AHost,APort);
  AHandle.Send(LBuf,0);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -