1993-03-28 - alt.hackers post

Header Data

From: Eric Hughes <hughes@soda.berkeley.edu>
To: cypherpunks@toad.com
Message Hash: 3ee7fbba6c486a4b4b48614cf20b6bd1d8289768820054ac7a81f3f9b017d755
Message ID: <9303282007.AA00701@soda.berkeley.edu>
Reply To: N/A
UTC Datetime: 1993-03-28 17:26:28 UTC
Raw Date: Sun, 28 Mar 93 09:26:28 PST

Raw message

From: Eric Hughes <hughes@soda.berkeley.edu>
Date: Sun, 28 Mar 93 09:26:28 PST
To: cypherpunks@toad.com
Subject: alt.hackers post
Message-ID: <9303282007.AA00701@soda.berkeley.edu>
MIME-Version: 1.0
Content-Type: text/plain

Rusty Babani forwarded me my hackers postings from six months ago.


Here they are (in two messages).

From: hughes@soda.berkeley.edu (Eric Hughes)
Newsgroups: alt.hackers
Subject: Remailer that will run on a user account
Date: 25 Sep 92 16:17:25 GMT
Distribution: alt
Organization: /accounts/hughes/.organization
Lines: 347

What follows are a couple of postings to the recently formed
cypherpunks mailing list.  They are tutorial in form because
the list is not entirely hackers.

Enjoy and deploy.



How to Make an Automated Remailer in Your Copious Spare Time with Easy
to Find and Inexpensive Software Tools You May Have Lying Around.

<reprinted from Popular Cryptography, September 1992. Used with permission>

The basic remailer illustrates how to hook in automated software
processing into the Unix mail system.  Here are the basic elements.

1. .forward
2. slocal and .maildelivery
3. remail.perl
4. /usr/lib/sendmail

1. .forward

Unix mail provides a way to have accounts on many different machines
but to receive all your mail in one place.  That facility is the
.forward file, which resides in the home directory.  The file is one
line long and contains the email address to which the mail will be

But the .forward file has another mode of operation.  If the string
begins with the pipe character '|', the mail will be piped through the
program listed.  Enclose the string with double quotes if you need
spaces included.  Here is my .forward file:

"| /usr/local/lib/mh/slocal -user hughes"

Thus all my mail gets processed by the slocal program, described next.

I don't know where the man page for .forward is.  Perhaps someone
could provide a reference.


2. slocal and .maildelivery

The software system MH contains a bunch of useful tools for handling
mail, only one of which we need.  For details on MH, do 'man mh'.

MH has a nice little mail hook processor called slocal.  Its docs can
be found by 'man mhook'.  slocal can conditionally perform operations
on mail messages and consider them either delivered or not.  It allows
multiple operations on individual mail messages.

slocal reads the file .maildelivery when it starts up for
instructions. Here is my .maildelivery file:

# field			pattern	action/	string 
#				result	(quote included spaces)
Request-Remailing-To	""	pipe R	"perl remail.perl" 
Request-Remailing-To	""	file R	archive.remailer

The various pieces of the .maildelivery file are fully documented in
the man page.  I'll just explain what mine does.  Each line describes
one operation to be performed on each incoming mail message.  Fields
are separated by whitespace, so if you need to include spaces, use

The first field, labelled field, is the mail header field to look for.
slocal can selectively process on any header line.  If the header line
does not exist, then the mail does not match this line and no
operation is performed.  If the header line does exist, processing

The second field, pattern, is a text string to match with the contents
of that header line, i.e. with everything after the colon.  In my
case, I put the empty string in, which matches everything.  You need
the pair of quotes to have a placeholder for the field contents.

The next field, action, tells what to do with the message.  'pipe'
sends the message to the standard input of the named program.  'file'
appends the message to an archive or log file.  A useful pipe command
for testing is "tee foo", which makes a copy of the message in file
foo, but does not append, so that you get an exact copy of what slocal
is going to pass to your pipe.  This allows testing of the pipe
program without sending yourself mail all the time.

The next field, result, tells what to do with the message after
processing.  I am currently using R for Regardless to indicate that
this action should always be performed no matter what.  The code R
indicates that the mail should be considered not delivered after
processing; thus slocal writes the mail back into my local spool and I
see it as normal.  Later, after I'm sick of looking at all the
forwarded mail, I'll change this code to A, meaning if the processing
succeeds, then the mail is considered delivered.  The archive file
will always remain R.

The last field, string, is the parameter to the action.  It is a file
name or program.  Use quotes to include spaces.  The name of my mail
processor is "perl remail.perl", which is to run the perl script
remail.perl on the mail.

The .maildelivery file is also the place to put encryption hooks to
automatically decrypt the bodies of messages.  More on that in a
future version.


3. remail.perl

Perl is a wonderful language for doing all sorts of useful work like
processing mail headers.  Do 'man perl' for details, or get the
O'Reilly book and really learn how to use it.

The perl script, in summary, strips off the mail headers, saving the
Subject: line, rewrites a new header, and appends the body of the
previous message.  Here is the script:

--------- cut here ---------
while (<>) {
	last if /^$/ ;
	$subject = $_ if /^Subject:/ ;
	if (/^Request-Remailing-To:/) {
		chop ;
		s/^.*:// ;
		$addressee = $_ ;

#open( OUTPUT, ">foo" ) || die "Cannot open 'foo'." ;
open( OUTPUT, "| /usr/lib/sendmail " . $addressee ) ;
select( OUTPUT ) ;

print "To:" . $addressee . "\n" ;
print "From: nobody\n" ;
print $subject ;
print "Remailed-By: Eric Hughes <hughes@soda.berkeley.edu>\n" ;
print "\n" ;

while (<>) {
} continue {
	print ;
--------- cut here ---------

Here is a summary of the operation.  To really understand this, you'll
have to learn perl.

The while loop processes standard input.  'last' terminates the loop
as soon as a blank line is seen.  A blank line separates the header
from the body.  The subject line, if seen, sets the subject variable
to the whole subject line.  The Request- header line has its final
newline removed, the contents up to the colon substituted into
nonexistence, and saves the rest in the addressee variable.

Next the pipe to sendmail is opened and its output is selected so that
all print commands will go to the pipe.  There is a comment for a
different output channel to the file foo which can be commented in for

Next the remailed header is constructed out of print statements.

Lastly the rest of the standard input is passed through unmodified to
the output channel.  The while loop terminates when there is no more


4. sendmail

sendmail is the backend mailer; it expects complete mail messages and
does not usually generate any line itself except for the first "From"
(with no colon) line.  Any header you construct will thus get passed
through mostly unmodified.  Hence you can put in any "From:" line you
want and any other header info, such as my "Remailed-By:" line.

sendmail expects the name of the addressee on its command line,
otherwise it puts an "Apparently-To:" line in the header.

Any mail processor which remails should probably go through sendmail,
although it would also be possible to talk to an SMTP port directly,
were you so motivated.  MH also has some remailing programs; see 'man


A few words for tinkerers.

-- You can always send mail to yourself.  Especially after you've done
one kind of mail processing and want to pass the mail through the
filters again.

-- When getting started, create an empty .maildelivery file first and
then get your .forward file working.  Test it by sending messages to
yourself.  If you're not getting them, they are going into the bit
bucket.  All your other mail will as well, in this case, so if you
can't afford to lose mail, do it right the first time or work on a
spare account.  

-- Any mail slocal does not process will get delivered as normal.
Running a remailer will not interfere with your other work.

-- Remember to use quote marks.

-- You don't need to be a sysadmin to run this kind of remailer.
There is nothing, however, to prevent a sysadmin from running this
sofware under an alias.  The sysadmin is also a 'trusted user' to
sendmail and can get rid of pesky "From"-no-colon lines.

-- Perl has a random function which could be used to automatically
choose various "From:" lines from a database.  Remember to include

-- postnews or inews could be substituted for sendmail.  Different
header lines would have to be created.  Such a service could run in
parallel with a remailer.  You too can now repost to alt.sex.bondage!

Enjoy.  And watch for interesting improvements like encryption.


The hopping remailer is finished.  I wrote it this morning.

The change to make a hopping remailer is very easy.  Here's the new
perl script:

--------- cut here ---------
while (<>) {
	last if /^$/ ;
	$subject = $_ if /^Subject:/ ;
	if (/^Request-Remailing-To:/) {
		chop ;
		s/^.*:// ;
		$addressee = $_ ;

#open( OUTPUT, ">foo" ) || die "Cannot open 'foo'." ;
open( OUTPUT, "| /usr/lib/sendmail " . $addressee ) ;
select( OUTPUT ) ;

print "To:" . $addressee . "\n" ;
print "From: nobody\n" ;
print $subject ;
print "Remailed-By: Eric Hughes <hughes@soda.berkeley.edu>\n" ;

# check to see if there are header lines in the body to collapse 
#   into the full header.

if ( $_ = <> ) {
	if (/^##$/) {
		# do nothing if the pasting token appears
		# the rest of the body will be directly appended
		# this allows for extra header lines to be added
	} else {
		# normal line
		print "\n" ;
		print $_ ;
} else {
	# empty body
	exit ;

while (<>) {
} continue {
	print ;
--------- cut here ---------

Short explanation.  The 'print "\n" ;' line was moved inside the new
if statement.  The if statement reads a line of the body and stops the
script if there is no body.  The line read is tested to see if it
contains the two characters "##" alone on the line.  "##" is the ANSI
C token pasting operator.  If there is no pasting, a blank line is
printed to mark the end of the header and the first line of the body
is printed.  If there is pasting, then the conditional does nothing,
which has the effect that the body is appended directly onto the end
of the header, allowing you to add more header lines after the header
is rewritten.

Here is a sample message that I sent myself after the new script was

--------- cut here ---------
To: hughes
Subject: multiple hops
Request-Remailing-To: hughes

X-Hop: 1
Request-Remailing-To: hughes

X-Hop: 2
Request-Remailing-To: hughes

X-Hop: 3

This is a test message of multiple hops.

--------- cut here ---------

I received four pieces of mail after sending this to myself.  The
first was the actual letter, which is still delivering normally and
not being filtered.  The next two were the first and second
remailings; they had X-Hop: 1 and 2.  The last message was the final
one, had X-Hop: 3 in its header and was delivered normally.

At each stage, the header got rewritten and a new
Request-Remailing-To: line inserted.  When that mail got delivered, it
was again rewritten, with a new remailing request.  This process is
extensible up to the 50K or so practical limitatation on mail size.

Note that this system is not at all secure by itself.  But if each
message body were encrypted first, and the message first decrypted
before the header re-write took place, the routing instructions as a
whole would be hidden from prying eyes.

That's the next project.



To be on the cyhperpunks mailing list, mail to 


I'll put you on.