As I started a new company, I was stranded for a few weeks (thanks to the local telco and the company registration office) with no ADSL link, no optical fiber link, and no leased line to the Internet. The only thing that remained for me to use was my trusty old USR 33.6Kbps dial-up modem and a dial-up account. We greatly needed communication, with email the most pressing need. So I sat down and started to think about what I could do to solve this problem.
I had a domain name and a dial-up link with no fixed IP. My personal machine at home plugged into a HNS Direcway Satellite Link 128/2048Kbps and had a fixed IP address. I naturally thought I could do something with all of this.
In a former life, I set up some large UUCP systems, when the Internet had not made its way into the everyday life and PPP did not exist. I took a look at age-old UUCP and decided there must be some way to run UUCP in order to attain my goals.
UUCP is the Land Rover of data communication. It is an old protocol dating back the inception of Unix, Arpanet, Usenet, and the Internet. I have personally so far used it over:
|
Related Reading
The Complete FreeBSD |
As you can see, the venerable UUCP is something of an all-terrain vehicle. It deserves the utmost respect, as I do not know of any other protocol that has retained such versatility throughout its history (apart from TCP/IP, of course). I searched the net and stumbled on several articles, one written in 2001 by a compatriot of mine, Fabien Penso of LinuxFR and uucpssh.org fame. Fabien described a system of UUCP over SSH that was exactly what I needed. Although he wrote his article well, it left much unsaid and applied to an old version of SSH and a Linux environment, which in my case did me no good since I am using FreeBSD. However, Fabien's article provided me with the starters. Thanks Fabien. :)
Undoubtedly, there are other ways (such as port redirection in SSH, etc.) to run this setup. This is the way I chose. I welcome all other comments and additions that readers can provide in order to enhance this article in the future.
The POP protocol is no solution for people (like me) who want to fetch their email in a practical and efficient manner from multiple locations, be it from a dial-up account or a fixed Internet link. Thus, it seemed to me that UUCP over SSH provides great benefits for those people.
UUCP is a batched protocol; therefore, it enables you to leave your email unpolled for long periods of time without risking its loss. ETRN does not, and too many providers will garbage collect unread POP3 or IMAP email on a regular basis.
UUCP is also resilient on failed transfers and can resume unfinished transfers where they stopped. This is by design, as it originated on unreliable links. So far, I know of no other email transfer protocol capable of this feat. Other protocols will retransfer the whole shebang every time there is an error.
UUCP does not require you to have a permanent link to the Internet.
However, UUCP has one minor inconvenience: you will neither receive instant responses to your emails nor the error messages. At best, you'll receive them on the next UUCP poll your system places.
UUCP can poll at any time interval you wish, allowing you to queue mail for a whole network for as long as you wish. It can also transfer data as files--not necessarily attached to emails. You can fetch a news feed in the Usenet fashion and/or create your own newsgroups, and last but not least, execute remote commands and send yourself back the results in an email. I merely wanted my email, though.
Here are the assumptions I've made for my explanation:
sshd running. Fortunately,
this is the default under FreeBSD.postfconf | grep mail_version.The networking setup calls:
server.domain.tld and a
UUCP name of server.client.domain.tld and
its UUCP name client.To install Postfix on the client, install it from the /usr/ports/mail/postfix/ FreeBSD port. Edit /usr/local/etc/posftix/main.cf to resemble the following:
myhostname = machine.localdomain.local
myorigin = $mydomain
inet_interfaces = $myhostname, localhost
mydestination = $myhostname, localhost.$mydomain, $mydomain
local_recipient_maps = unix:passwd.byname $alias_maps
mynetworks = $config_directory/mynetworks
relay_domains = $config_directory/relay_domains
transport_maps = hash:$config_directory/transport
alias_maps = hash:$config_directory/aliases
alias_database = hash:/etc/aliases
This sets up the Postfix environment. You may already have done this when you installed Postfix for other usage.
Edit /usr/local/etc/posftix/main.cf to add:
disable_dns_lookups=yes
This tells Postfix not to try resolving names through DNS when sending email to the server, because that would bypass the UUCP connection to try sending through SMTP instead.
Create a file called /etc/postfix/transport, containing the following:
################### this is POSTFIX 'transport' file #############################
# Every time this file is modified it need a 'postmap' and postfix needs a reload#
##################################################################################
hosted-domain.tld : # this domain emails are delivered locally
.hosted-domain.tld : # this domain emails are delivered locally
# in case you need subdomains or machine routing
* uucp:server # All other emails get transported by UUCP
This change introduces a new transport type, namely UUCP, on the last line
of the file. It tells Postfix that any email that is not
something@hosted-domain.tld or
something@<subdomain>.hosted-domain.tld needs to use the
UUCP transport. As for hosted-domain.tld and
.hosted-domain.tld, their respective transport is :,
which tells Postfix to deliver email for these domains locally.
Now tell Postfix about these changes by issuing the command:
$ postmap /usr/local/etc/postfix/transport && postfix reload
Create a file called /usr/local/etc/postfix/virtual, containing:
#################### This is POSTFIX 'virtual' file ##############################
# Every time this file is modified it need a 'postmap' and postfix needs a reload#
##################################################################################
########### hosted-domain.tld virtual users table ##############
postmaster@hosted-domain.tld postmaster@localdomain.local
virtualuser1@hosted-domain.tld localuser1@localdomain.local
Tell Postfix about these changes with the command:
$ postmap /usr/local/etc/postfix/virtual && postfix reload
Create a file called /usr/local/etc/postfix/mynetworks, containing:
#################### This is POSTFIX 'mynetworks' file ###########################
# Every time this file is modified it need a 'postmap' and postfix needs a reload#
##################################################################################
xxx.xxx.xxx.xxx/xx OK # where xxx.xxx.xxx.xxx is your local private IP address
# and /xx is the mask for your networks for exple
# 192.168.1.1/24
xxx.xxx.xxx.xxx OK # single host for exemple 192.168.2.1
127.0.0.0/8 OK # this is localhost interface(s)
This file lists which IP addresses can send email through this machine using SMTP to the client just before being queued by UUCP for sending to the UUCP server.
You may also want to modify the canonical file in order to rewrite emails sent by the local daemon or users. To do this, modify the /usr/local/postfix/canonical file with something like this:
#################" This is POSTFIX 'canonical' file ##############################
# Every time this file is modified it need a 'postmap' and postfix needs a reload#
##################################################################################
@localdomain.local @hosted-domain.tld
Again, tell Postfix about these changes:
$ postfix stop && postfix start
In case you modified aliases, it's always a good idea also to run
newaliases and then postfix reload. You can also
(this is the way I do things) make a shell script that rebuilds all of the
necessary files and reloads or restart Postfix when you change a file. For
example, here is the very simple script I made:
#! /bin/sh
postmap virtual
postmap transport
postmap mynetworks
postmap relays_domains
postmap access
postmap canonical
newaliases
postfix reload
Use postcheck to check that your configuration is valid.
|
To set up the UUCP client, you need to create several files in /etc/uucp. Start by creating a file called /etc/uucp/sys, containing:
###### this is the 'sys' file for Taylor UUCP ######
system server
alias server-ssh
call-login *
call-password *
time any
address server.domain.tld
port ssh
protocol t
remote-send /var/spool/uucppublic
remote-receive /var/spool/uucppublic
Next, create a file called /etc/uucp/port, containing:
###### this is the 'port' file for Taylor UUCP ######
port ssh
type pipe
command /usr/bin/ssh -x -o batchmode=yes server.domain.tld
Create a file called /etc/uucp/call, containing:
###### this is the 'call' file for Taylor UUCP ######
server login password
Finally, set the permissions on these files appropriately. SSH is very paranoid about file permissions. The commands are:
% cd /var/spool/ && chmod go-w uucp
% cd /etc/uucp && chown root:uucp * && chmod 550 *
Now it's time to configure SSH on the client to use UUCP. Run vipw
uucp as root to change the uucp user's home directory
from
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
to
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucp:/usr/libexec/uucp/uucico
Next, generate SSH keys for the client:
% su -m uucp
$ export HOME=/var/spool/uucp
$ cd /var/spool/uucp
$ ssh-keygen -t dsa
The final command will prompt you for a password. Don't type one. Just
press the return key. Though this seems like a big security hole, it's not as
bad as it looks; the uucp user does not have a password in
/etc/passwd, so anyone who can run programs as that user must
already have an account on the client with fairly good permissions.
This step generates an SSH v2 DSA key set; the id_dsa.pub public key file will come in handy later.
Congratulations! You have finished the client side of the configuration.
The server needs Postfix, UUCP, and SSH configured and running correctly.
I take for granted that because this is the main mail server, you already know how to configure Postfix in order for it to be able to send and receive emails from and to the Internet.
Postfix must know to transport all email originating from the client through the UUCP transport, with no exceptions. To do this, create a file called /usr/local/etc/postfix/transport, containing:
####### this is POSTFIX 'transport' file #########
hosteddomain.tld uucp:client
Postfix also needs to accept relaying to your domains, as well. Create a file called /usr/local/etc/postfix/relay_domains, containing:
####### this is POSTFIX 'relay_domains file #########
hosted-domain.tld OK
hosted-domain.tld OK
Then tell Postfix about the changes:
% postmap transport relay_domains && postfix reload
The same Postfix rebuilding file above can be just as useful here.
In /etc/passwd, use vipw uucp as root to change
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucp:/usr/libexec/uucp/uucico
to
uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucp:/bin/sh
Next, create a file called /etc/uucp/sys, containing:
###### this is the UUCP 'sys' file for Taylor UUCP #######
# client
system client
time any
port tcp
protocol t
remote-send /var/spool/uucppublic
remote-receive /var/spool/uucppublic
# other clients use the same lines
Out of paranoia, I recommend to tell UUCP that the directory for
remote-send and remote-receive is
/var/spool/uucppublic.
Create a file called /etc/uucp/passwd, containing:
###### this is the UUCP 'passwd' file for Taylor UUCP #######
yourlogin yourpassword
That's all of the server-side UUCP configuration.
The final server step is its SSH configuration. Switch to the UUCP user by
doing su -m uucp, then create the authorized_keys
file:
$ touch /var/spool/uucp/.ssh/authorized_keys
Copy the content of the client's id_dsa.pub file (located in /var/spool/uucp/.ssh/) into /var/spool/uucp/.ssh/authorized_keys on the server. To assuage SSH's paranoid permissions check, perform the following command:
chmod go-rwx && chown uucp:uucp
Edit the authorized_keys file with the editor of your choice and insert this before its content:
command="/usr/libexec/uucp/uucico -l
The file should now read something like:
command="/usr/libexec/uucp/uucico -l" ssh-dss AAAAB3NzaC1kc3MAAACBA...
Be aware that the DSA key should all fit on one long line; there must be no carriage return.
Once you have done the above, do cd /var/spool/ && chmod go-w
uucp. This should make SSH less paranoid about these file
permissions.
Congratulations. You have finished the server configuration.
The end is in sight. Now register the DSA key from with the client's SSH /var/spool/uucp/.ssh/known_hosts file. You only need to do this once.
Switch to the UUCP user (su -m uucp), then connect to the
server with ssh -v uucp@server.domain.tld. Answer "yes" when SSH
asks you if you want to add the DSA public key of the server to your list of
known and trusted hosts.
At this point, all incoming mail destined for hosted-domain.tld will end up
spooled and stored in the /var/spool/uucp/client directory of the
server. UUCP will gladly send it to the client whenever it calls in through
the SSH tunnel.
If this does not work for you, then you forgot something along the way. Check again your Postfix configuration and UUCP configuration on either or both the client and the server.
You can now test your setup from the client.
Dial-up your Internet provider using PPP if you need to. Skip this step if you have a permanent link to the Internet.
Do su -m uucp followed by /usr/libexec/uucp/uucico -f
-sserver. To see mail flowing in, type uulog -f -sserver.
If you need to watch what happens to the email after Postfix receives it, check
the Postfix log file with tail -f /var/lo/maillog.
Now fire up your email client (Mozilla mail, Thunderbird, sylpheed, nmh,
emacs, etc.) and send some mail. You should now also see it being
spooled in the UUCP queue (uustat -sserver) and waiting to be sent
out to the server next time you launch uucico.
Note that you can use uustat -k <jobid> on the client
or the server to kill any job(s) seen by using uusat -s
<system>. You'll see something like:
server.NI8whUuAALf1 server uucp 10-06 10:35 Executing rmail \
user@domain.tld (sending 1452 bytes)
Type uustat -k system.NI8whUuAALf1 to remove this job from the
UUCP queue before it is sent out.
I encourage anyone who wants to have a deeper understanding of all of the
possibilities of UUCP to read the info file info UUCP or the PDF
file for Taylor UUCP, which is an invaluable source of information.
Now the final touch: if you want to launch this automatically and you have a
permanent Internet connection, add a cron job to /var/cron/tabs/uucp.
As root, do crontab -u uucp -e and insert the content below,
modifying the parameters as you wish. This example polls the UUCP server every
five minutes:
# This is Taylor UUCP crontab file
PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/libexec/uucp
0-55/5 * * * * /usr/libexec/uucp/uucico -f -sserver
I hope you enjoyed this little tutorial and that you can put UUCP to work for your own usage. I would like to find out how many people in the world are using UUCP, so please send me email if you are, so that I can compile a list of countries and a number of users.
(I based this article on Fabien Penso's "UUCP+SSH: La Maniére Idéale de Récuperer vos Mails!")
Christophe Prévotaux is the founder of Origami Systems Sarl, a French telco/ISP and custom solutions provider.
Return to the BSD DevCenter.
Copyright © 2009 O'Reilly Media, Inc.