From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 3EC121FD5A for ; Fri, 30 Apr 2021 09:24:39 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 7/8] net_reader: Net::NNTP --proxy=socks5h:// support Date: Fri, 30 Apr 2021 09:24:37 +0000 Message-Id: <20210430092438.20926-8-e@80x24.org> In-Reply-To: <20210430092438.20926-1-e@80x24.org> References: <20210430092438.20926-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Since Net::NNTP doesn't support Socket or RawSocket options/accessors like Mail::IMAPClient does; we must perform localized @ISA manipulation and massage Net::NNTP into using IO::Socket::Socks rather than IO::Socket::IP. This is a bit fragile, but Net::Cmd and Net::NNTP rarely change; and I keep an eye on them, anyways. --- MANIFEST | 2 ++ lib/PublicInbox/NetNNTPSocks.pm | 33 +++++++++++++++++++++++++++++++++ lib/PublicInbox/NetReader.pm | 12 +++++++++++- xt/net_nntp_socks.t | 22 ++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 lib/PublicInbox/NetNNTPSocks.pm create mode 100644 xt/net_nntp_socks.t diff --git a/MANIFEST b/MANIFEST index 5933ddf4..bc2ad671 100644 --- a/MANIFEST +++ b/MANIFEST @@ -241,6 +241,7 @@ lib/PublicInbox/NDC_PP.pm lib/PublicInbox/NNTP.pm lib/PublicInbox/NNTPD.pm lib/PublicInbox/NNTPdeflate.pm +lib/PublicInbox/NetNNTPSocks.pm lib/PublicInbox/NetReader.pm lib/PublicInbox/NetWriter.pm lib/PublicInbox/NewsWWW.pm @@ -518,6 +519,7 @@ xt/lei-auth-fail.t xt/mem-imapd-tls.t xt/mem-msgview.t xt/msgtime_cmp.t +xt/net_nntp_socks.t xt/net_writer-imap.t xt/nntpd-validate.t xt/perf-msgview.t diff --git a/lib/PublicInbox/NetNNTPSocks.pm b/lib/PublicInbox/NetNNTPSocks.pm new file mode 100644 index 00000000..8495204a --- /dev/null +++ b/lib/PublicInbox/NetNNTPSocks.pm @@ -0,0 +1,33 @@ +# Copyright (C) 2021 all contributors +# License: AGPL-3.0+ + +# wrap Net::NNTP client with SOCKS support +package PublicInbox::NetNNTPSocks; +use strict; +use v5.10.1; +use Net::NNTP; +our %OPT; +our @ISA = qw(IO::Socket::Socks); +my @SOCKS_KEYS = qw(ProxyAddr ProxyPort SocksVersion SocksDebug SocksResolve); + +# use this instead of Net::NNTP->new if using Proxy* +sub new_socks { + my (undef, %opt) = @_; + require IO::Socket::Socks; + local @Net::NNTP::ISA = (qw(Net::Cmd), __PACKAGE__); + local %OPT = map {; + defined($opt{$_}) ? ($_ => $opt{$_}) : () + } @SOCKS_KEYS; + Net::NNTP->new(%opt); # this calls our new() below: +} + +# called by Net::NNTP->new +sub new { + my ($self, %opt) = @_; + @OPT{qw(ConnectAddr ConnectPort)} = @opt{qw(PeerAddr PeerPort)}; + my $ret = $self->SUPER::new(%OPT) or + die 'SOCKS error: '.eval('$IO::Socket::Socks::SOCKS_ERROR'); + $ret; +} + +1; diff --git a/lib/PublicInbox/NetReader.pm b/lib/PublicInbox/NetReader.pm index ac23e701..b2c4fee2 100644 --- a/lib/PublicInbox/NetReader.pm +++ b/lib/PublicInbox/NetReader.pm @@ -116,7 +116,13 @@ sub try_starttls ($) { sub nn_new ($$$) { my ($nn_arg, $nntp_opt, $uri) = @_; - my $nn = Net::NNTP->new(%$nn_arg) or die "E: <$uri> new: $!\n"; + my $nn; + if (defined $nn_arg->{ProxyAddr}) { + eval { $nn = PublicInbox::NetNNTPSocks->new_socks(%$nn_arg) }; + die "E: <$uri> $@\n" if $@; + } else { + $nn = Net::NNTP->new(%$nn_arg) or die "E: <$uri> new: $!\n"; + } # default to using STARTTLS if it's available, but allow # it to be disabled for localhost/VPN users @@ -170,6 +176,10 @@ sub nn_for ($$$$) { # nn = Net::NNTP SSL => $uri->secure, # snews == nntps %$common, # may Debug .... }; + if ($lei && $lei->{socks5h}) { + require PublicInbox::NetNNTPSocks; + %$nn_arg = (%$nn_arg, %{$lei->{socks5h}}); + } my $nn = nn_new($nn_arg, $nntp_opt, $uri); if ($cred) { $cred->fill($lei); # may prompt user here diff --git a/xt/net_nntp_socks.t b/xt/net_nntp_socks.t new file mode 100644 index 00000000..4a144fd8 --- /dev/null +++ b/xt/net_nntp_socks.t @@ -0,0 +1,22 @@ +#!perl -w +# Copyright (C) 2021 all contributors +# License: AGPL-3.0+ +use v5.12; +use PublicInbox::TestCommon; +use URI; +require_mods 'IO::Socket::Socks'; +use_ok 'PublicInbox::NetNNTPSocks'; +my $url = $ENV{TEST_NNTP_ONION_URL} // + 'nntp://czquwvybam4bgbro.onion/inbox.comp.mail.public-inbox.meta'; +my $uri = URI->new($url); +my $on = PublicInbox::NetNNTPSocks->new_socks( + Port => $uri->port, + Host => $uri->host, + ProxyAddr => '127.0.0.1', # default Tor address + port + ProxyPort => 9050, +) or xbail('err = '.eval('$IO::Socket::Socks::SOCKS_ERROR')); +my ($nr, $min, $max, $grp) = $on->group($uri->group); +ok($nr > 0 && $min > 0 && $min < $max, 'nr, min, max make sense') or + diag explain([$nr, $min, $max, $grp]); +is($grp, $uri->group, 'group matches'); +done_testing;