How to use TIdWhois with SOCKS proxy - delphi

I'm getting whois information using this code:
IdWhois1.Host := 'whois.nic.tld';
ServerResultStr := IdWhois1.WhoIs('google.tld');
But I need to query the whois server (port 43) using a SOCKS proxy server.
I'm using Delphi 10.3.3. Is there any way to achieve this by using TIdWhois?

SOCKS is handled in Indy using the TIdSocksInfo component. You can configure it with the proxy details as needed (Host, Port, Version, Authentication, etc).
To make TIdWhois (or any TCP client) connect to its target server through TIdSocksInfo, you need to do the following:
assign a TIdIOHandlerSocket-derived component (TIdIOHandlerStack, or any TIdSSLIOHandlerSocketBase-derived component, like TIdSSLIOHandlerSocketOpenSSL) to the TIdWhois.IOHandler property.
assign the TIdSocksInfo to the IOHandler's TransparentProxy property.

Related

Indy TIdSocksServer not forwarding traffic

I am attempting to create a SOCKS 4/5 server, and I would like to use the Indy TIdSocksServer component as the foundation. It seems straight forward enough and simple to use, but I must be missing something.
I dropped a TIdSocksServer onto a new Form and configured the following:
Active: True
AllowSocks4: True
AllowSocks5: True
Bindings: 0.0.0.0:43334
Default Port: 80
Intercept: null
IOHandler: null
I added code to display 'connect' in a TMemo upon connection:
procedure TForm1.IdSocksServer1Connect(AContext: TIdContext);
begin
Memo1.Lines.Add('connect');
end;
I configured ProxyChains on a Linux host:
/etc/proxychains.conf
...
socks5 10.0.0.56 43334
When I execute the App and try to connect using ProxyChains, I get the following error:
kelly#ubuntu:~/home$ proxychains curl www.google.com
ProxyChains-3.1 (http://proxychains.sf.net)
|DNS-request| www.google.com
|S-chain|-<>-10.0.0.56:43334-<><>-4.2.2.2:53-<--timeout
|DNS-response|: www.google.com does not exist
curl: (6) Could not resolve host: www.google.com
I can confirm that the connection is established, because the text 'connect' gets added to the Memo. I also used Wireshark and observed the three-way handshake and teardown between my Ubuntu host and the Windows host.
It seems the issue is that the traffic is reaching the SOCKS server, but not getting forwarded. I acknowledge that this is absolute minimum code, but I am under the impression that the TIdSocksServer component would take care of forwarding the traffic, and I would add in supporting functions such as validating credentials for SOCKS5, etc.
Remy identified the issue with my code. In order to verify that the server was receiving connections I added a procedure which wrote to a TMemo component, which was causing a deadlock. To fix the error all I had to do was remove the procedure which was updating the TMemo component. Works as expected.

Delphi Indy https request with custom DNS resolving

example url:
https://api.binance.com/api/v1/time
Using TIdDNSResolver and cloudflare dns I can get the host IP.
direct request in the form of
https://205.251.219.20/api/v1/time
doesn't work cause as I understand the server expects to see "api.binance.com" in the url. (it doesnt work even in browser)
Using synapce and the following patch to replace request's host with resolved IP I make it working
function THTTPSend.InternalDoConnect(needssl: Boolean): Boolean;
begin
Result := False;
FSock.CloseSocket;
FSock.Bind(FIPInterface, cAnyPort);
if FSock.LastError <> 0 then
Exit;
If ResolvedIP.IsEmpty
then FSock.Connect(FTargetHost, FTargetPort)
else FSock.Connect(ResolvedIP, FTargetPort); // !!
Is there any way to do the same using Indy?
By default, TIdHTTP uses the Host:Port that is specified/inferred by the URL that is being requested. To change that behavior, you would have to alter TIdHTTP's source code, such as in the TIdCustomHTTP.SetHostAndPort() or TIdCustomHTTP.CheckAndConnect() method (which are both not virtual), and then recompile Indy.
Alternatively, you could use TIdHTTP's OnSocketAllocated or On(Before|After)Bind event (which are not promoted to published in TIdHTTP, so you would have to access them manually at runtime) to change the TIdHTTP.IOHandler.Host property to whatever IP address you want to connect to. This will not have any affect on the HTTP headers that TIdHTTP sends, such as Host, which will still be taken from the URL.
Alternatively, if you want all of Indy's Host-to-IP DNS queries to go through Cloudflare, you could derive a custom class from TIdStack (or whatever platform-specific descendant you are interested in, such as TIdStackWindows), override its virtual HostByName() method to perform whatever DNS query you want, and then pass your class type to the SetStackClass() function in the IdStack unit at program startup before any Indy classes are instantiated.

Delphi Web.HTTPApp.TWebRequest RemoteIP VS RemoteAddr

TWebRequest has two metnod for retrive the client IP Address:
RemoteIP
RemoteAddr
From docs of RemoteIP:
Specifies the IP of the remote target machine associated with the HTTP
request message. Read the RemoteIP property to obtain the IP address
of the remote target machine associated with the HTTP request message.
From docs of RemoteAddr:
Indicates the remote IP address of the client associated with the HTTP
request message. Read RemoteAddr to obtain the IP address of the
source of the Web client request.
They seem very close but RemoteIP return an empty string.
I want retrieve the client ip address, what is the right method?
If we look into source code we will find the following in the declaration of TWebRequest
property RemoteIP: string read GetRemoteIP;
property RemoteAddr: string index 21 read GetStringVariable;
Implementation:
function TWebRequest.GetRemoteIP: string;
begin
Result := EmptyStr;
end;
and GetStringVariable is a virtual method.
Let's look into one of child classes - TISAPIRequest, we will find the following:
LResult := GetFieldByNameA(ServerVariables[Index]);
ServerVariables[21] is 'REMOTE_ADDR' header, which shows IP of client or proxy server.
But there is no implementation for GetRemoteIP.
It looks like RemoteIP isn't used in requests, because TCGIRequest, TApacheRequest and TWinCGIRequest also don't implement GetRemoteIP.

Making a http request trough Socks proxy

I have a socks proxy and I need to make a HTTP Get request
I tried using indy using this sample ( http://www.indyproject.org/KB/index.html?howdoiuseaproxywithindy.htm ) but I always get the error :
Connection closed gracefully.
What am I doing wrong ?
The correct way to handle this is to assign a TIdIOHandlerStack component to the TIdHTTP.IOHandler property, then assign a TIdSocksInfo component to the TIdIOHandlerStack.TransparentProxy property, and then configure the TIdSocksInfo as needed.

How to check server connection

i want to check my server connection to know if its available or not to inform the user..
so how to send a pkg or msg to the server (it's not SQL server; it's a server contains some serviecs) ...
thnx in adcvance ..
With all the possibilities for firewalls blocking ICMP packets or specific ports, the only way to guarantee that a service is running is to do something that uses that service.
For instance, if it were a JDBC server, you could execute a non-destructive SQL query, such as select * from sysibm.sysdummy1 for DB2. If it's a HTTP server, you could create a GET packet for index.htm.
If you actually have control over the service, it's a simple matter to create a special sub-service to handle these requests (such as you send through a CHECK packet and get back an OKAY response).
That way, you avoid all the possible firewall issues and the test is a true end-to-end one. PINGs and traceroutes will be able to tell if you can get to the machine (firewalls permitting) but they won't tell you if your service is functioning.
Take this from someone who's had to battle the network gods in a corporate environment where machines are locked up as tight as the proverbial fishes ...
If you can open a port but don't want to use ping (i dont know why but hey) you could use something like this:
import socket
host = ''
port = 55555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
while 1:
try:
clientsock, clientaddr = s.accept()
clientsock.sendall('alive')
clientsock.close()
except:
pass
which is nothing more then a simple python socket server listening on 55555 and returning alive

Resources