Override Firefox, LWP::UserAgent and curl DNS resolution
This post is part of the notes I took while preparing for and during the migration of https://perlmonks.org behind a CDN. I mostly publish these notes so that I can find them again later.
There are situations where I don't want to override the DNS resolution for my complete system, but still connect to specific machines pretending a DNS name resolves to them. Examples are SSL certificate checking, and various firewall configurations. Especially while migrating a site behind a CDN or when setting up s site beh[nd a reverse proxy or Wireguard, I want to inspect and compare the results of queries to the different machines.
For these examples, assume that 10.0.0.1 is the machine serving the website
perlmonks.org as the origin. The public DNS resolves to a pool of CDN machines
somewhere else, but we want to debug what the original source is serving.
The original machine also wants to be accessed as perlmonks.org over SSL.
Override curl name resolution
This is documented in the curl manpage
curl --resolve perlmonks.org:443:10.0.0.1 https://...
Override Firefox name resolution
Open the Firefox browser console with Ctrl+Shift+J . You should be able to enter Javascript there; If not, enable "Debugging Tools für Browser-Chrome" in the normal browser console settings (F12 , then F1 yeah, CUI standards be damned ). Then enter the name/IP pair for name resolution. This persists until you restart Firefox.
const gOverride = Cc["@mozilla.org/network/native-dns-override;1"].getService(Ci.nsINativeDNSResolverOverride);
gOverride.addIPOverride("perlmonks.org", "10.0.0.1");
Override LWP::UserAgent DNS name resolution
For LWP::UserAgent there is no general mechanism, but monkeypatching LWP::Protocol::https works. To also make SNI work, you
should additionally pass in the SSL_hostname explicitly to the SSL options. I'm not sure why this is necessary, as the code in LWP::Protocol::https
extracts the hostname from the request URL, but this made the difference for me between 421 Misdirected Request and 200 OK with Fastly :
our $force_peeraddr;
around 'LWP::Protocol::http::_extra_sock_opts' => sub {
my $orig = shift;
die unless wantarray;
my @rv = $orig->(@_);
push @rv, PeerAddr => $force_peeraddr if defined $force_peeraddr;
return @rv;
};
around 'LWP::Protocol::https::_get_sock_info' => sub {
my $orig = shift;
my ($self, $res, $sock) = @_;
my $cert = $sock->get_peer_certificate;
my @san = $cert->peer_certificate('subjectAltNames');
use Data::Dumper; warn Dumper \@san;
while (@san) {
my ($type_id, $value) = splice @san, 0, 2;
$res->push_header("Client-SSL-Cert-SubjectAltName"
=> "$type_id: $value");
}
$orig->(@_);
};
$force_peeraddr = '10.0.0.1';
my $ua = LWP::UserAgent->new(
ssl_opts => {
verify_hostname => 0,
SSL_hostname => 'perlmonks.org', # for SNI
},
timeout => 60,
);
Override Chrome name resolution
It seems that this is not possible.
Override wget name resolution
It seems that this is not possible.