Exit Remailer Suggestion
Someone wrote:
What about AOL disks? We need shorter lived, disposable remailers as exit remailers... Let them take the heat, while the real remailers walk. Lets see a series of "exitman" remailers. Exitman remailers are walking targets left to fend for themselves as long as they may.
We already have a preconfigured set of exit remailers. They have names like "hotmail", "rocketmail", etc... These are the web-based email services which will instantly create accounts for anyone, no questions asked or authentication required, and permit access to these accounts with the chosen password from anywhere on the Net. You can even chain them, using an account on one to apply for an instant account on another, leaving few bread crumbs for anyone to follow. Most of these services don't care, don't log, and rarely read their email to abuse@. Even if pressure does cause an occasional account to be deleted, you can easily create ten more in as many seconds. By reconfiguring current remailers to use a public Email service as the last link in the chain, we tap a potentially infinite supply of disposable accounts, on advertising-supported service providers with skins as thick as those of the bulk emailers. Sounds like a plan to me. -- Mike Duvos $ PGP 2.6 Public Key available $ enoch@zipcon.com $ via Finger $ {Free Cypherpunk Political Prisoner Jim Bell}
Mike Duvos <enoch@zipcon.net> writes:
Someone wrote:
(That someone was me).
What about AOL disks? We need shorter lived, disposable remailers as exit remailers... Let them take the heat, while the real remailers walk. Lets see a series of "exitman" remailers. Exitman remailers are walking targets left to fend for themselves as long as they may.
By reconfiguring current remailers to use a public Email service as the last link in the chain, we tap a potentially infinite supply of disposable accounts, on advertising-supported service providers with skins as thick as those of the bulk emailers.
Sounds like a plan to me.
OK, lets _do_ it! Sounds much easier and less risky than relying on a recreational cracker to provide a stream of short lived remailers as I was suggesting. Adam -- Have *you* exported RSA today? --> http://www.dcs.ex.ac.uk/~aba/rsa/ print pack"C*",split/\D+/,`echo "16iII*o\U@{$/=$z;[(pop,pop,unpack"H*",<> )]}\EsMsKsN0[lN*1lK[d2%Sa2/d0<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<J]dsJxp"|dc`
Here's version 1.2 of sendhotmail. Now the only configuration option in the perl script itself is the location of a config file. That file should have the following form (you should change the pathnames of the local files, of course): ---8<--- sample config file ---8<--- ## The URL from which to fetch the current list of active proxies Proxy List URL: http://www.publius.net/~remailer/proxy_list.txt ## The file in which to cache the above list Proxy List Cache File: /home/iang/sendhotmail/proxy_list.txt ## How many days to cache the proxy list Proxy List Cache Age: 1 ## The file containing the list of hotmail accounts Account List File: /home/iang/sendhotmail/accountlist ---8<--- sample config file ---8<--- Also, you'll need a list of valid hotmail account names/passwords in the account list file to which you pointed, above. This file contains a number of lines, each of the form "login:password". For example: ---8<--- sample accountlist file ---8<--- ldeliverer:xxxx ---8<--- sample accountlist file ---8<--- sendhotmail now picks a proxy and hotmail account at random. I'll try to keep the proxy list relatively up-to-date, and you need to keep your account list up-to-date (in case Hotmail shuts one down, or something). The perl program will "die" if something unexpected happens (such as the proxy it chose didn't work, or the hotmail account was suddenly invalid). Just try running it again (future versions will likely automatically retry with different random choices for the proxy and the hotmail login). - Ian #!/usr/bin/perl -w ## ## sendhotmail: pipe an RFC822 mail message into this, and it will send it ## out from a hotmail account via an HTTP proxy ## ## Program by Ian Goldberg <ian@cypherpunks.ca> ## use LWP; $uadirect = new LWP::UserAgent; ## The filename of the configuration file $configfile = '/home/iang/sendhotmail/config'; ## Read the config file open(CONFIG, $configfile) or die "Cannot open $configfile: $!\n"; while(<CONFIG>) { next if /^\s*$/o; next if /^\s*\#/o; next unless /^([^:]+):\s*(.*)$/o; $value = $2; $name = "\L$1\E"; $name =~ s/[^a-z0-9]//iog; $config{$name} = $value; } close(CONFIG); ## Get the proxy list $proxylisturl = new URI::URL ($config{'proxylisturl'} || 'http://www.publius.net/~remailer/proxy_list.txt'); if (defined $config{'proxylistcachefile'}) { ## Check if the locally cached copy is new enough $maxage = $config{'proxylistcacheage'} || 1; if (! -e $config{'proxylistcachefile'} || -M $config{'proxylistcachefile'} > $maxage) { ## Fetch a new copy $request = new HTTP::Request('GET', $proxylisturl); $request->header(Pragma => 'no-cache'); $response = $uadirect->request($request); $body = $response->content; $newfname = $config{'proxylistcachefile'}.".new.$$"; open(CACHE, ">$newfname") or die "Cannot write $newfname: $!\n"; print CACHE $body; close(CACHE); rename($newfname, $config{'proxylistcachefile'}) or die "Cannot rename $newfname: $!\n"; } ## Read the proxy list open(CACHE, $config{'proxylistcachefile'}) or die "Cannot open $config{'proxylistcachefile'}: $!\n"; @proxylist = grep (s/\n// && /^[^#]/, <CACHE>); close(CACHE); } else { ## Just fetch from the net $request = new HTTP::Request('GET', $proxylisturl); $request->header(Pragma => 'no-cache'); $response = $uadirect->request($request); @proxylist = grep (/^[^#]/, split("\n", $response->content)); } @proxylist = ('secure.escape.ca:80') if $#proxylist == -1; ## Get the account list if (defined $config{'accountlistfile'}) { open(ACC, $config{'accountlistfile'}) or die "Cannot open $config{'accountlistfile'}: $!\n"; @accountlist = grep (s/\n// && /^[^#]/, <ACC>); close(ACC); } @accountlist = ('ldeliverer:xxxx') if $#accountlist == -1; sub escapetext { my $t = $_[0]; $t =~ s/([\000-\037\200-\377\{\}\|\\\^\[\]\`\"\<\>\:\@\/\;\?\=\&\%\.\#])/"%".unpack('H2',$1)/eg; $t =~ s/ /+/g; $t; } sub getaddrs { my @addrlist = split(/,\s*/, $_[0]); my ($a, $ra); my @r; foreach $a (@addrlist) { $ra = ''; if ($a =~ /\<(.*?)\>/) { $ra = $1; } else { $a =~ s/\(.*?\)//g; $a =~ s/\".*?\"//g; $ra = $1 if $a =~ /(\S+\@\S+)/; } push (@r, $ra) if $ra ne ''; } join(', ', @r); } ## Parse the incoming mail. We need to put the To, Cc, and Bcc headers ## into a simple format that hotmail can understand. $header{'to'} = ''; $header{'subject'} = ''; $header{'cc'} = ''; $header{'bcc'} = ''; $curheader = ''; while(<STDIN>) { last if /^$/; chomp; if (/^\S/) { ## Start a new header if (s/^To:\s*//io) { $curheader = 'to'; $header{'to'} .= ', ' if $header{'to'} ne ''; } elsif (s/^Cc:\s*//io) { $curheader = 'cc'; $header{'cc'} .= ', ' if $header{'cc'} ne ''; } elsif (s/^Bcc:\s*//io) { $curheader = 'bcc'; $header{'bcc'} .= ', ' if $header{'bcc'} ne ''; } elsif (s/^Subject:\s*//io) { $curheader = 'subject'; } else { $curheader = ''; } } if ($curheader ne '') { s/^\s*//; $header{$curheader} .= ' ' if $header{$curheader} ne ''; $header{$curheader} .= $_; } } $header{'to'} = &getaddrs($header{'to'}); $header{'cc'} = &getaddrs($header{'cc'}); $header{'bcc'} = &getaddrs($header{'bcc'}); $msg = &escapetext(join('', <STDIN>)); ## Choose a proxy and account at random srand(time ^ $$); $proxy = $proxylist[int rand ($#proxylist+1)]; ($login, $passwd) = $accountlist[int rand ($#accountlist+1)] =~ /^([^:]*):(.*)$/; ## Begin hotmail-specific magic $ua = new LWP::UserAgent; $ua->proxy('http', "http://${proxy}/"); $url = new URI::URL 'http://www.hotmail.com/cgi-bin/password.cgi'; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("login=${login}&curmbox=ACTIVE"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\"/io or die "Cannot log in"; $url = new URI::URL $1, $url; $body = $'; $body =~ s/\<\s*\/form\s*\>.*//; $body =~ /\<\s*input\s+[^>]*name=\"disk\"\s+value(=\"(.*?)\")?/io or die "Cannot give passwd"; $disk = $2 || ""; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("passwd=${passwd}&frames=no&disk=${disk}&curmbox=ACTIVE&login=${login}&js=no"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/compose.*?)\"/io or die "Cannot compose"; $composeurl = new URI::URL $1, $url; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/logout.*?)\"/io or die "Cannot compose"; $logouturl = new URI::URL $1, $url; $request = new HTTP::Request('GET', $composeurl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\".*?\>/io or die "Cannot send message"; $url = new URI::URL $1, $composeurl; $body = $'; $data = ''; while(1) { $body =~ /^\s*\<\s*input\s+type=\"?hidden\"?\s+name=\"(.*?)\"\s+value(=\"(.*?)\")?\s*\>/io or last; $name = $1; $value = $3 || ""; $body = $'; $data .= $name."=".$value."&"; } $data .= "to=$header{'to'}&subject=$header{'subject'}&cc=$header{'cc'}&bcc=$header{'bcc'}&body=${msg}&Send.x=1&Send.y=1"; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content($data); $response = $ua->request($request); $body = $response->content; $request = new HTTP::Request('GET', $logouturl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request);
Ian writes:
Here's version 1.2 of sendhotmail.
This is truly beautiful. How long until hotmail is the default for everything coming out of a mixmaster that isn't going to another remailer? -- Mike Duvos $ PGP 2.6 Public Key available $ enoch@zipcon.com $ via Finger $ {Free Cypherpunk Political Prisoner Jim Bell}
And here's 1.3. It uses the same config file as 1.2. New: o fixes a bug involving + in email addresses o handles continuation headers properly o Can be used as a drop-in replacement for sendmail (though it may get confused if you pass weird sendmail options); it will keep trying random hotmail accounts and proxies until it succeeds in delivering the mail. Note that, depending on your connectivity, this can take a while... - Ian #!/usr/bin/perl -w ## ## sendhotmail: pipe an RFC822 mail message into this, and it will send it ## out from a hotmail account via an HTTP proxy ## ## Version 1.3: 19970813 ## ## Program by Ian Goldberg <ian@cypherpunks.ca> ## sub Usage { die "Usage: $0 -t | addr\@host ...\n"; } ## Check options $cmdlineto = ''; while ($#ARGV >= 0 && $ARGV[0] =~ /^-/o) { $_ = shift @ARGV; if ($_ eq "-t") { $cmdlineto = ''; } elsif ($_ eq "-f") { shift @ARGV; } else { ## Ignore option } } if ($#ARGV >= 0) { $cmdlineto = join(", ", @ARGV); } use LWP; $uadirect = new LWP::UserAgent; ## The filename of the configuration file $configfile = '/home/iang/sendhotmail/config'; ## Read the config file open(CONFIG, $configfile) or die "Cannot open $configfile: $!\n"; while(<CONFIG>) { next if /^\s*$/o; next if /^\s*\#/o; next unless /^([^:]+):\s*(.*)$/o; $value = $2; $name = "\L$1\E"; $name =~ s/[^a-z0-9]//iog; $config{$name} = $value; } close(CONFIG); sub escapetext { my $t = $_[0]; $t =~ s/([\000-\037\200-\377\{\}\|\\\^\[\]\`\"\<\>\:\@\/\;\?\=\&\%\.\#\+])/"%".unpack('H2',$1)/eg; $t =~ s/ /+/g; $t; } sub getaddrs { my @addrlist = split(/,\s*/, $_[0]); my ($a, $ra); my @r; foreach $a (@addrlist) { $ra = ''; if ($a =~ /\<(.*?)\>/) { $ra = $1; } else { $a =~ s/\(.*?\)//g; $a =~ s/\".*?\"//g; $ra = $1 if $a =~ /(\S+\@\S+)/; } push (@r, $ra) if $ra ne ''; } join(', ', @r); } ## Parse the incoming mail. We need to put the To, Cc, and Bcc headers ## into a simple format that hotmail can understand. $header{'to'} = ''; $header{'subject'} = ''; $header{'cc'} = ''; $header{'bcc'} = ''; $curheader = ''; while(<STDIN>) { last if /^$/; chomp; if (/^\S/) { ## Start a new header if (s/^To:\s*//io) { $curheader = 'to'; $header{'to'} .= ', ' if $header{'to'} ne ''; } elsif (s/^Cc:\s*//io) { $curheader = 'cc'; $header{'cc'} .= ', ' if $header{'cc'} ne ''; } elsif (s/^Bcc:\s*//io) { $curheader = 'bcc'; $header{'bcc'} .= ', ' if $header{'bcc'} ne ''; } elsif (s/^Subject:\s*//io) { $curheader = 'subject'; } else { $curheader = ''; } } if ($curheader ne '') { s/^\s*//; $header{$curheader} .= ' ' if $header{$curheader} ne ''; $header{$curheader} .= $_; } } ## If we were given command-line addresses, that overrides the headers $header{'to'} = &getaddrs($cmdlineto eq '' ? $header{'to'} : $cmdlineto); $header{'cc'} = &getaddrs($cmdlineto eq '' ? $header{'cc'} : ''); $header{'bcc'} = &getaddrs($cmdlineto eq '' ? $header{'bcc'} : ''); $msg = &escapetext(join('', <STDIN>)); srand(time ^ $$); ## Keep trying until the message is successfully delivered RETRYLOOP: while (1) { ## Get the proxy list $proxylisturl = new URI::URL ($config{'proxylisturl'} || 'http://www.publius.net/~remailer/proxy_list.txt'); if (defined $config{'proxylistcachefile'}) { ## Check if the locally cached copy is new enough $maxage = $config{'proxylistcacheage'} || 1; if (! -e $config{'proxylistcachefile'} || -M $config{'proxylistcachefile'} > $maxage) { ## Fetch a new copy $request = new HTTP::Request('GET', $proxylisturl); $request->header(Pragma => 'no-cache'); $response = $uadirect->request($request); $body = $response->content; $newfname = $config{'proxylistcachefile'}.".new.$$"; open(CACHE, ">$newfname") or die "Cannot write $newfname: $!\n"; print CACHE $body; close(CACHE); rename($newfname, $config{'proxylistcachefile'}) or die "Cannot rename $newfname: $!\n"; } ## Read the proxy list open(CACHE, $config{'proxylistcachefile'}) or die "Cannot open $config{'proxylistcachefile'}: $!\n"; @proxylist = grep (s/\n// && /^[^#]/, <CACHE>); close(CACHE); } else { ## Just fetch from the net $request = new HTTP::Request('GET', $proxylisturl); $request->header(Pragma => 'no-cache'); $response = $uadirect->request($request); @proxylist = grep (/^[^#]/, split("\n", $response->content)); } @proxylist = ('secure.escape.ca:80') if $#proxylist == -1; ## Get the account list if (defined $config{'accountlistfile'}) { open(ACC, $config{'accountlistfile'}) or die "Cannot open $config{'accountlistfile'}: $!\n"; @accountlist = grep (s/\n// && /^[^#]/, <ACC>); close(ACC); } @accountlist = ('ldeliverer:xxxx') if $#accountlist == -1; ## Choose a proxy and account at random $proxy = $proxylist[int rand ($#proxylist+1)]; ($login, $passwd) = $accountlist[int rand ($#accountlist+1)] =~ /^([^:]*):(.*)$/; #print STDERR "Trying $login through $proxy\n"; ## Begin hotmail-specific magic $ua = new LWP::UserAgent; $ua->proxy('http', "http://${proxy}/"); $url = new URI::URL 'http://www.hotmail.com/cgi-bin/password.cgi'; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("login=${login}&curmbox=ACTIVE"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\"/io or next RETRYLOOP; $url = new URI::URL $1, $url; $body = $'; $body =~ s/\<\s*\/form\s*\>.*//; $body =~ /\<\s*input\s+[^>]*name=\"disk\"\s+value(=\"(.*?)\")?/io or next RETRYLOOP; $disk = $2 || ""; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("passwd=${passwd}&frames=no&disk=${disk}&curmbox=ACTIVE&login=${login}&js=no"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/compose.*?)\"/io or next RETRYLOOP; $composeurl = new URI::URL $1, $url; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/logout.*?)\"/io or next RETRYLOOP; $logouturl = new URI::URL $1, $url; $request = new HTTP::Request('GET', $composeurl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\".*?\>/io or next RETRYLOOP; $url = new URI::URL $1, $composeurl; $body = $'; $data = ''; while(1) { $body =~ /^\s*\<\s*input\s+type=\"?hidden\"?\s+name=\"(.*?)\"\s+value(=\"(.*?)\")?\s*\>/io or last; $name = $1; $value = $3 || ""; $body = $'; $data .= $name."=".$value."&"; } $data .= "to=$header{'to'}&subject=$header{'subject'}&cc=$header{'cc'}&bcc=$header{'bcc'}&body=${msg}&Send.x=1&Send.y=1"; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content($data); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*title\s*\>\s*Hotmail\s*-\s*Mailbox/io or next RETRYLOOP; $request = new HTTP::Request('GET', $logouturl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request); last RETRYLOOP; ## Success }
In article <199708080936.KAA01816@server.test.net>, Adam Back <aba@dcs.ex.ac.uk> wrote:
Mike Duvos <enoch@zipcon.net> writes:
Someone wrote:
(That someone was me).
What about AOL disks? We need shorter lived, disposable remailers as exit remailers... Let them take the heat, while the real remailers walk. Lets see a series of "exitman" remailers. Exitman remailers are walking targets left to fend for themselves as long as they may.
By reconfiguring current remailers to use a public Email service as the last link in the chain, we tap a potentially infinite supply of disposable accounts, on advertising-supported service providers with skins as thick as those of the bulk emailers.
Sounds like a plan to me.
OK, lets _do_ it!
Sounds good to me. Hotmail makes a note of the IP address that connected to it, but luckily there's no shortage of HTTP proxies out there... - Ian #!/usr/bin/perl -w ## ## sendhotmail: pipe an RFC822 mail message into this, and it will send it ## out from a hotmail account via an HTTP proxy ## ## Initial revision 19970808 by Ian Goldberg <ian@cypherpunks.ca> ## ## Set the following to your proxy host and port. ## Look at the files pointed at by ## http://ircache.nlanr.net/Cache/Tracker/caches/ ## for sample entries, but most of them don't allow just anyone to connect ## to hotmail through them. $proxyhost = 'proxy.slt.lk'; $proxyport = 8080; ## This is your hotmail login name and password $login = ## Fill this in yourself $passwd = ## Fill this in yourself ## End Configuration sub escapetext { my $t = $_[0]; $t =~ s/([\000-\037\200-\377\{\}\|\\\^\[\]\`\"\<\>\:\@\/\;\?\=\&\%\.\#])/"%".unpack('H2',$1)/eg; $t =~ s/ /+/g; $t; } ## Parse the incoming mail (note that we don't handle continuation headers) ## Also, the To, Cc, and Bcc headers ought to be in a form hotmail understands ## (no full names, etc.). We try to do the stripping properly. $to = ''; $subject = ''; $cc = ''; $bcc = ''; while(<STDIN>) { if (/^To:\s+(.*)/io) { $to = $1; $to =~ s/\(.*?\)//g; $to =~ s/\".*?\"//g; $to = &escapetext($to); } elsif (/^Subject:\s+(.*)/io) { $subject = &escapetext($1); } elsif (/^Cc:\s+(.*)/io) { $cc = $1; $cc =~ s/\(.*?\)//g; $cc =~ s/\".*?\"//g; $cc = &escapetext($cc); } elsif (/^Bcc:\s+(.*)/io) { $bcc = $1; $bcc =~ s/\(.*?\)//g; $bcc =~ s/\".*?\"//g; $bcc = &escapetext($bcc); } last if /^$/; } $msg = &escapetext(join("\r\n", <STDIN>)); use LWP; ## Begin magic $ua = new LWP::UserAgent; $ua->proxy('http', "http://${proxyhost}:${proxyport}/"); $url = new URI::URL 'http://www.hotmail.com/cgi-bin/password.cgi'; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("login=${login}&curmbox=ACTIVE"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\"/io or die "Cannot log in"; $url = new URI::URL $1, $url; $body = $'; $body =~ s/\<\s*\/form\s*\>.*//; $body =~ /\<\s*input\s+[^>]*name=\"disk\"\s+value(=\"(.*?)\")?/io or die "Cannot give passwd"; $disk = $2 || ""; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content("passwd=${passwd}&frames=no&disk=${disk}&curmbox=ACTIVE&login=${login}&js=no"); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/compose.*?)\"/io or die "Cannot compose"; $composeurl = new URI::URL $1, $url; $body =~ /\<\s*area\s+[^>]*href=\"(\/cgi-bin\/logout.*?)\"/io or die "Cannot compose"; $logouturl = new URI::URL $1, $url; $request = new HTTP::Request('GET', $composeurl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request); $body = $response->content; $body =~ /\<\s*form\s+[^>]*action=\"(.*?)\".*?\>/io or die "Cannot send message"; $url = new URI::URL $1, $composeurl; $body = $'; $data = ''; while(1) { $body =~ /^\s*\<\s*input\s+type=\"?hidden\"?\s+name=\"(.*?)\"\s+value(=\"(.*?)\")?\s*\>/io or last; $name = $1; $value = $3 || ""; $body = $'; $data .= $name."=".$value."&"; } $data .= "to=${to}&subject=${subject}&cc=${cc}&bcc=${bcc}&body=${msg}&Send.x=1&Send.y=1"; $request = new HTTP::Request('POST', $url); $request->header(Pragma => 'no-cache'); $request->content($data); $response = $ua->request($request); $body = $response->content; $request = new HTTP::Request('GET', $logouturl); $request->header(Pragma => 'no-cache'); $response = $ua->request($request);
participants (4)
-
Adam Back -
iang@cs.berkeley.edu -
iang@CS.Berkeley.EDU -
Mike Duvos