Clear WinInet DNS cache programmatically - caching

WinINet library caches IP address for any URL accessed over it. Because of this, when IP address for that URL gets changed then also WinInet library's HttpSendRequest goes to older IP address.
And, if older IP is responding, then WinINet will send all http request to older IP only.
Is there any way to force clean DNS cache of WinInet?
Or
Is there any way to force WinINet to send HTTP request to specified IP address (as we are able to get newer IP using gethostbyname())?
Note :
gethostbyname is giving me newer IP address, So this behaviour is happening of WinINet's caching.
I have tried "method 2" suggested in this MS article, but it didn't help
Sample code

You can try to use the flag when connecting:
INTERNET_FLAG_DONT_CACHE = 0x04000000 Does not add the returned entity
to the cache. This is identical to the preferred value,
INTERNET_FLAG_NO_CACHE_WRITE.
Or you can take a look at the DeleteUrlCacheEntry from the WinInet documentation here
I beleave this should do the trick.
--UPDATE
From this doc I've seen that there is an better flag to use it, look at the:
INTERNET_FLAG_PRAGMA_NOCACHE
Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
--UPDATE
As tested by #Pradeep you can change this registry keys to work it:
HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\DnsCacheEnabled
ServerInfoTimeOut and DnsCacheTimeout to 0.

Related

OpenSIPS 2.4 call forbidden

I discovered OpenSIPS and all the possibilities a few days ago. I would just use it as a simple SIP proxy to get started. Proxy between my designated UAC and my UAS (asterisk, not natted). The goal is to use a proxy to prevent bot attacks on my UAS.
After installing OpenSIPS, I tried to configure my XLITE (natted) by simply adding the proxy URL in the configuration. It works, I register and I can see in my UAS peers my extensions with proxy IP. But when I make a call, I got a forbidden error. In debug mode, the log does not talk to me, I see a lot of information but nothing about this error.
I did not make any changes to the default configuration script. Is this behavior normal?
I also tried with VM on public IP as UAC (so not named), same thing.
Thank you for your help.
Olivier
Most likely, your SIP INVITE is hitting this block:
if (!is_myself("$rd")) {
send_reply("403", "Relay Forbidden");
exit;
}
What this means is that your OpenSIPS does not consider itself responsible for the domain (or IP) that your SIP UA has placed in the Request-URI and is trying to route towards. To fix this, just whitelist the Asterisk IP as a local (recognized) domain using the alias statement:
listen = udp:*:5060
alias = 1.1.1.1

TIdHTTP indy component and IPVersion property (firemonkey)

i am using the TIdHTTP component on a multi-device app (building in Rad Studio Tokyo 10.2.3). All i'm doing is downloading a file to my local app folder (iOS). I want to make sure it works with IPv6 but i don't see the "IPVersion" property for TIdHTTP. I see it on other indy components in rad studio (e.g. IdFTP).
Is there a way to set IPVersion in code for the TIdHTTP component? Below is a snip of the code i'm using to download the file. If it fails on IPv4 it is supposed to try IPv6 next:
UnicodeString LFileName = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), "myfile.txt");
TFileStream* fs = new TFileStream(LFileName, fmCreate);
Form1->TIdHTTP->ConnectTimeout = 8000; // give it 8 seconds
Form1->TIdHTTP->ReadTimeout = 8000;
try
{
UnicodeString URL = "http://myservername.com/myfile.txt";
Form1->TIdHTTP->Get(URL, fs);
Form1->TIdHTTP->Disconnect();
// ShowMessage("Good download via IPv4");
}
catch(const System::Sysutils::Exception &)
{
try
{
Form1->TIdHTTP->Disconnect(); // clean up from IPv4 try
UnicodeString URL = "http://[myservername.com]/myfile.txt";
Form1->TIdHTTP->Get(URL, fs);
Form1->TIdHTTP->Disconnect();
// ShowMessage("Good download via IPv6");
Righ now i just put brackets around the domain name in hopes that this would work for IPv6...i won't know for sure until i can get a truly IPv6 only network setup (working on it).
UPDATE: I just had an app accepted to Apple Store that uses this approach so obviously it passed IPv6 testing. FYI
I found this discussion in which Remy Lebeau states:
TIdHTTP parses IP version info only from the URL itself, so if you need to send a request to an IPv6 target (IP address or hostname), you have to tell TIdHTTP to use IPv6 by wrapping the hostname portion of the URL in square brackets, eg:
s := idHTTP.Post('http://[IPv6 address or hostname]/resource', ...);
Otherwise TIdHTTP uses IPv4 instead.
This bracketed syntax is a requirement when using IPv6 address literals in
URLs, per RFCs 2732 and 3986. But when using a hostname instead, there is
no such syntax requirement. Connecting to a hostname requires a DNS lookup
to discover the host's available IP addresses and their respective IP versions, and then connect to those addresses as needed until one succeeds.
Indy does not currently implement that kind of connection model. It first
allocates a socket based on the client's IPVersion property, THEN performs
a DNS request suited for that IPVersion, and then finally connects to the
first IP address reported by DNS. This is a known limitation of Indy, which
would require a redesign of Indy's internal logic to fix. However, it can
be worked around manually in most Indy client components by performing
your own DNS lookup ahead of time and then looping through the results, setting Indy's Host and IPVersion properties and calling Connect() on each loop iteration.
However, TIdHTTP is a special case, because it derives the Host and IPVersion values from the requested URL, overriding anything the calling code might set manually. However, it is also because of this model that would potentially allow TIdHTTP to be updated to perform its own DNS loop internally without having to rewrite all of Indy's client components to match. Except that Indy does not currently implement a function that returns all of the IP addresses of a hostname, only the first IP address of a particular version. Until such a function is added to Indy in a cross-platform manner, TIdHTTP cannot be updated to auto-detect IPv4/IPv6 hosts.
As such, this confirms my approach should work (trying IPv4 first and then IPv6 if that fails) using the brackets.
Also, I edited my code to show a "Disconnect" prior to trying the IPv6 in case the IPv4 left a mess.

Are the ip addresses automatically cached in the recursive DNS when it is returned from the authoritative DNS?

It is said that the recursive DNS refers to its cache first before performing recursive search on the authoritative DNS. So, I wanted to know how is the DNS caching done. Is it automatic or if no, what happens? How is the DNS record cached?
Unless you are running a DNS server, then the caching is being done by your client or and LDNS. Your system runs something called a resolver (set of libraries in linux, DNS client service on windows) whose job it is to take names and turn them into IP address, hopefully following the TTL of the returned records. Additionally, browsers and other applications may also add their own level of caching, often not adhering to the TTL returned for the record.
Additionally, your machine will point to another server, either locally or your ISP's, that is your LDNS (local DNS). This is a configuration that's required for proper functioning because it must be specified by IP address, either manually entered or obtained via a mechanism like DHCP.

Ruby: force dns resolution through custom dns server

I want to resolve the DNS requests issued from within a Ruby script through a DNS server, different from the ones in resolv.conf. While I could do that manualy by using Resolv::DNS or something like that, I'd like to do that for all the requests (like the ones issued by RestClient, for example). Any ideas?
RestClient uses net/http and uses the host name part of the provided URL to open a TCP socket:
https://github.com/ruby/ruby/blob/trunk/lib/net/http.rb?source=cc#L879
The simplest way to change which host is accessed is to manually change the URL to use an IP address by performing the lookup yourself.
Alternatively, you can replace the resolver of the various *Socket classes, and there is actually an example of how to do this here: https://github.com/ruby/ruby/blob/4c2304f0004e9f1784540f3d36976aad9eab1f68/lib/resolv-replace.rb

How to find out the remote Address in node.js if it is HTTPS request?

HI. in node.js, if it is http request, I can get the remoteAddress at req.connection.remoteAddress,
so, how to get it if https request? I find there is req.socket.remoteAddress but I'm not sure. Please advice. thanks.
It appears something is strange/broken indeed.
As of node 0.4.7, it seems http has remoteAddress available on:
req.connection.remoteAddress
req.socket.remoteAddress
on https, both of these are undefined, but
req.connection.socket.remoteAddress
does work.
That one isn't available on http though, so you need to check carefully.
I cannot imagine this behavior is intentional.
Since googling "express js ip" directly points to here, this is somehow relevant.
Express 3.0.0 alpha now offers a new way of retrieving IP adresses for client requests.
Simply use req.ip. If you're doing some proxy jiggery-pokery you might be interested in app.set("trust proxy", true); and req.ips.
I recommend you to read the whole discussion in the Express Google Group.
var ip = req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
Note that sometimes you can get more than one ip address in req.headers['x-forwarded-for'], specially when working with mobile phones accessing your server (wifi and carrier data).
As well req.headers['x-forwarded-for'] is easily manipulated so you need a properly configured proxy server.
Is better to check req.connection.remoteAddress against a list of known proxy servers before to go with req.headers['x-forwarded-for'].

Resources