LWPx::...idAgent(3pm)

πŸ“¦
version 1.12 Β· 2 versions
  • 1.12 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking (latest)
  • 1.12 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– LWPx::ParanoidAgent β€” the Perl manual page, bestie edition πŸ’–

okay so welcome to the docs for LWPx::ParanoidAgent, a 3pm manual page that ships with your Perl. grab a snack, we're getting paranoid (affectionately).


✨ NAME ✨

LWPx::ParanoidAgent β€” a subclass of LWP::UserAgent that literally protects you from harm πŸ›‘οΈβœ¨


🌸 SYNOPSIS 🌸

require LWPx::ParanoidAgent;

my $ua = LWPx::ParanoidAgent->new;

# this is 10 seconds overall, from start to finish.  not just between
# socket reads.  and it includes all redirects.  so attackers telling
# you to download from a malicious tarpit webserver can only stall
# you for $n seconds

$ua->timeout(10);

# setup extra block lists, in addition to the always-enforced blocking
# of private IP addresses, loopbacks, and multicast addresses

$ua->blocked_hosts(
   "foo.com",
   qr/\.internal\.company\.com$/i,
   sub { my $host = shift;  return 1 if is_bad($host); },
);

$ua->whitelisted_hosts(
   "brad.lj",
   qr/^192\.168\.64\.3?/,
   sub { ... },
);

# get/set the DNS resolver object that's used
my $resolver = $ua->resolver;
$ua->resolver(Net::DNS::Resolver->new(...));

# and then just like a normal LWP::UserAgent, because it is one.
my $response = $ua->get('http://search.cpan.org/');
...
if ($response->is_success) {
    print $response->content;  # or whatever
}
else {
    die $response->status_line;
}

πŸ¦‹ DESCRIPTION πŸ¦‹

LWPx::ParanoidAgent is a class that subclasses LWP::UserAgent, except it's paranoid about attackers. πŸ’… You reach for it when you're fetching a remote resource on behalf of a possibly malicious user. like, you don't know them, you don't trust them, and yet here you are fetching their stuff. bestie. the audacity.

This class can do everything LWP::UserAgent can (callbacks, uploads from files, all of it) β€” EXCEPT proxy support is explicitly removed, because in that case you should be doing your paranoia at your proxy. not here. proxy said "not my job" so this module said "periodt, removed."

Also, the schemes are limited to http and https, which map to LWPx::Protocol::http_paranoid and LWPx::Protocol::https_paranoid respectively β€” these are forked versions of the same ones without the _paranoid suffix. Subclassing them didn't look possible, because they were essentially just one huge function. 😭 iconic behaviour honestly.

So what does all this paranoia actually buy you? This class protects you from:

  • connecting to internal IP ranges (unless you whitelist them)
  • hostnames/IPs that you blacklist
  • a remote webserver tarpitting your process β€” the timeout parameter is changed to be a global timeout over the entire process
  • all combinations of redirects and DNS tricks used to otherwise tarpit and/or connect to internal resources

πŸŽ€ CONSTRUCTOR πŸŽ€

new

my $ua = LWPx::ParanoidAgent->new([ %opts ]);

In addition to any constructor options from LWP::UserAgent, you may also set:

  • blocked_hosts β€” set it to an arrayref
  • whitelisted_hosts β€” also an arrayref
  • resolver β€” a Net::DNS::Resolver object

πŸ‘‘ METHODS πŸ‘‘

  • $csr->resolver($net_dns_resolver)
  • $csr->resolver

Get/set the Net::DNS::Resolver object used to lookup hostnames. πŸ”βœ¨

  • $csr->blocked_hosts(@host_list)
  • $csr->blocked_hosts

Get/set the list of blocked hosts. The items in @host_list may be compiled regular expressions (with qr//), code blocks, or scalar literals. In any case, the thing that is matched, passed in, or compared (respectively) is all of the given hostname, given IP address, and IP address in canonical a.b.c.d decimal notation. so if you want to block "1.2.3.4" and the user entered it in a mix of network/host form in a mix of decimal/octal/hex β€” you need only block "1.2.3.4" and not worry about the details. no cap, that's the whole point. 🧚

  • $csr->whitelisted_hosts(@host_list)
  • $csr->whitelisted_hosts

Like blocked hosts, but matching the hosts/IPs that bypass blocking checks. The only difference is the IP address isn't canonicalized before being whitelisted-matched, mostly because it doesn't make sense for somebody to enter in a good address in a subversive way. like, why would you. πŸ™ˆ


🌈 SEE ALSO 🌈

See LWP::UserAgent to see how to use this class. πŸ‘€


πŸ’€ ISSUES πŸ’€

Report issues: https://github.com/collectiveintel/LWPx-ParanoidAgent/issues


😭 WARRANTY 😭

This module is supplied "as-is" and comes with no warranty, expressed or implied. It tries to protect you from harm, but maybe it will. Maybe it will destroy your data and your servers. πŸ’€ You'd better audit it and send me bug reports. fr fr.


πŸ™ˆ BUGS πŸ™ˆ

Maybe. See the warranty above. 😌


 Copyright 2005 Brad Fitzpatrick
 Copyright 2013 Wes Young (wesyoung.me)

Lot of code from the base class, copyright 1995-2004 Gisle Aas.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


and that's the whole page, bestie πŸ’– this was perl v5.36.0, dated 2022-11-27 β€” go forth and fetch responsibly, stay paranoid, and remember: proxy support is gone, it's not coming back. mwah 🫢✨

πŸ“¦ where this page comes from