The FTP server is frequently called ftpd. You may run it as a standalone daemon process that gets fired up at boot or you may choose to have it startup as needed by running it out of inetd. Generally, unless you are running a high-use, dedicated ftp server, you should run it out of inetd to save system resources. There are hooks for both setups in the OpenBSD /etc/rc.conf and /etc/inetd.conf files.
There are two main types of security issues when you are dealing with FTP. One type is shared with all server daemons: buggy code for which exploits can be developed. To guard against this sort of problem you simply have to pay attention to relevant mailing lists or websites so that you know immediately when an exploit for the server you use has been discovered. The second type of problem arises from mis-configuration errors that provide read or (worse) write permissions where such permissions shouldn't have been granted.
There several RFC documents that describe actual File Transfer Protocol. In particular, there is RFC-959, See: http://www.rfc-editor.org/rfc/rfc959.txt. The RFC defines, among other things, a series of 'requests' or commands, such as the following:
Request Description
ABOR abort previous command
CDUP change to parent of current working directory
CWD change working directory
DELE delete a file
HELP give help information
LIST give list files in a directory (``ls -lgA'')
MKD make a directory
PASS specify password
PASV prepare for server-to-server transfer
PORT specify data connection port
PWD print the current working directory
QUIT terminate session
RETR retrieve a file
STOR store a file
There are other commands (quite a few) and some servers support
other commands; generally there is a standard set that are always
supported, though!
Traditional FTP is known as active FTP. Let's use tcpdump to watch the traffic associated with an active FTP session.
I will be using an FTP client on xibalba and connecting to an FTP server on coatlicue. Here is the initial text of the client session:
xibalba % ftp coatlicue
Connected to coatlicue.
220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
Name (coatlicue:tor): anonymous
331 Guest login ok, type your name as password.
Password:
230 Guest login ok, access restrictions apply.
ftp>
And the initial tcpdump output:
coatlicue% sudo tcpdump -t -i le1 not ip src or dst 10.0.0.3
tcpdump: listening on le1
xibalba.4443 > coatlicue.ftp: S 657303158:657303158(0) win 32120 <mss
coatlicue.ftp > xibalba.4443: S 1666789549:1666789549(0) ack 65730315
xibalba.4443 > coatlicue.ftp: . ack 1 win 32120 <nop,nop,timestamp 63
coatlicue.ftp > xibalba.4443: P 1:56(55) ack 1 win 17376 <nop,nop,tim
xibalba.4443 > coatlicue.ftp: . ack 56 win 32120 <nop,nop,timestamp 6
xibalba.4443 > coatlicue.ftp: P 1:17(16) ack 56 win 32120 <nop,nop,ti
coatlicue.ftp > xibalba.4443: . ack 17 win 17376 <nop,nop,timestamp 4
coatlicue.ftp > xibalba.4443: P 56:105(49) ack 17 win 17376 <nop,nop,
xibalba.4443 > coatlicue.ftp: . ack 105 win 32120 <nop,nop,timestamp
xibalba.4443 > coatlicue.ftp: P 17:28(11) ack 105 win 32120 <nop,nop,
coatlicue.ftp > xibalba.4443: . ack 28 win 17376 <nop,nop,timestamp 4
coatlicue.ftp > xibalba.4443: P 105:153(48) ack 28 win 17376 <nop,nop
xibalba.4443 > coatlicue.ftp: P 28:34(6) ack 153 win 32120 <nop,nop,t
coatlicue.ftp > xibalba.4443: . ack 34 win 17370 <nop,nop,timestamp 4
coatlicue.ftp > xibalba.4443: P 153:192(39) ack 34 win 17376 <nop,nop
xibalba.4443 > coatlicue.ftp: . ack 192 win 32120 <nop,nop,timestamp
Next, if you do an ls command, watch what happens:
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for '/bin/ls'.
total 14
drwxr-xr-x 2 ftp 1003 512 Apr 26 14:32 bin
drwxr-xr-x 2 ftp 1003 512 Apr 26 14:36 etc
drwxr-xr-x 2 ftp 1003 512 Apr 26 14:33 pub
226 Transfer complete.
ftp>
The 'ls' command is transmitted on the already established
FTP command session:
xibalba.4443 > coatlicue.ftp: P 34:55(21) ack 192 win 32120 <nop,nop,
coatlicue.ftp > xibalba.4443: . ack 55 win 17376 <nop,nop,timestamp 4
coatlicue.ftp > xibalba.4443: P 192:222(30) ack 55 win 17376 <nop,nop
xibalba.4443 > coatlicue.ftp: P 55:61(6) ack 222 win 32120 <nop,nop,t
coatlicue.ftp > xibalba.4443: . ack 61 win 17370 <nop,nop,timestamp 4
Then, a second TCP connection is setup to transmit the data.
The catch, that defines an active FTP session, is that this data
connection is initiated by the FTP server:
coatlicue.ftp-data > xibalba.4444: S 1772957978:1772957978(0) win 163
xibalba.4444 > coatlicue.ftp-data: S 1520016762:1520016762(0) ack 177
coatlicue.ftp-data > xibalba.4444: . ack 1 win 18824 <nop,nop,timesta
coatlicue.ftp > xibalba.4443: P 222:277(55) ack 61 win 17376 <nop,nop
xibalba.4443 > coatlicue.ftp: . ack 277 win 32120 <nop,nop,timestamp
coatlicue.ftp-data > xibalba.4444: P 1:355(354) ack 1 win 18824 <nop,
xibalba.4444 > coatlicue.ftp-data: . ack 355 win 32120 <nop,nop,times
coatlicue.ftp > xibalba.4443: P 277:301(24) ack 61 win 17376 <nop,nop
coatlicue.ftp-data > xibalba.4444: F 355:355(0) ack 1 win 18824 <nop,
xibalba.4444 > coatlicue.ftp-data: . ack 356 win 32120 <nop,nop,times
xibalba.4444 > coatlicue.ftp-data: F 1:1(0) ack 356 win 32120 <nop,no
coatlicue.ftp-data > xibalba.4444: . ack 2 win 18824 <nop,nop,timesta
xibalba.4443 > coatlicue.ftp: . ack 301 win 32120 <nop,nop,timestamp
The fact that active FTP functions by having the data connections
initiated by the server makes it incompatible with most firewalls
that only allow return traffic for connections initiated on the
inside. One alternative is to rip a big hole in your firewall
that allows an TCP traffic through that comes from TCP port ftp-data.
I don't recommend you do that. A better alternative is to use passive
mode FTP.
Let's change to passive mode FTP and watch the traffic for the same ls command:
ftp> pass
Passive mode on.
ftp> ls
227 Entering Passive Mode (10,0,0,1,138,68)
...
The tcpdump output for the transmit of the 'ls' command:
xibalba.4445 > coatlicue.ftp: P 34:40(6) ack 192 win 32120 <nop,nop,ti
coatlicue.ftp > xibalba.4445: . ack 40 win 17376 <nop,nop,timestamp 46
coatlicue.ftp > xibalba.4445: P 192:237(45) ack 40 win 17376 <nop,nop,
xibalba.4445 > coatlicue.ftp: . ack 237 win 32120 <nop,nop,timestamp 6
And then the data connection is made. This time the connection is
initiated by the client (the definition of passive mode FTP):
xibalba.4446 > coatlicue.35396: S 2564476744:2564476744(0) win 32120 <
coatlicue.35396 > xibalba.4446: S 1901498010:1901498010(0) ack 2564476
xibalba.4446 > coatlicue.35396: . ack 1 win 32120 <nop,nop,timestamp 6
xibalba.4445 > coatlicue.ftp: P 40:46(6) ack 237 win 32120 <nop,nop,ti
coatlicue.ftp > xibalba.4445: . ack 46 win 17376 <nop,nop,timestamp 46
coatlicue.ftp > xibalba.4445: P 237:292(55) ack 46 win 17376 <nop,nop,
xibalba.4445 > coatlicue.ftp: . ack 292 win 32120 <nop,nop,timestamp 6
coatlicue.35396 > xibalba.4446: P 1:355(354) ack 1 win 17376 <nop,nop,
xibalba.4446 > coatlicue.35396: . ack 355 win 32120 <nop,nop,timestamp
coatlicue.ftp > xibalba.4445: P 292:316(24) ack 46 win 17376 <nop,nop,
coatlicue.35396 > xibalba.4446: F 355:355(0) ack 1 win 17376 <nop,nop,
xibalba.4446 > coatlicue.35396: . ack 356 win 32120 <nop,nop,timestamp
xibalba.4446 > coatlicue.35396: F 1:1(0) ack 356 win 32120 <nop,nop,ti
coatlicue.35396 > xibalba.4446: . ack 2 win 17376 <nop,nop,timestamp 4
xibalba.4445 > coatlicue.ftp: . ack 316 win 32120 <nop,nop,timestamp 6
You can see there is a big difference between the two modes of FTP.
It shouldn't be surprising that
many sites do not allow active FTP through their firewalls.
Also, passive mode FTP will simply 'work' with the firewall setups
that we have talked about in class.
We just saw an example of anonymous FTP in the previous section. The point of anonymous FTP is to provide a 'guest' account that anyone may use. This of course brings in a boatload of security implications (but not many more than FTP has already, given the fact that it is an insecure protocol - passwords and data are passed as cleartext). In particular, you must ensure that the anonymous user does not have access to sensitive system files.
When you use anonymous FTP, the server still requires you to enter a password. The convention is that the user enters her email address as a password. Some FTP servers will accept any old string of text, while others require the address to be an RFC compliant address.
The typical way that access to a machine is restricted, with modern FTP servers, is to use the chroot(2) system call. In this way, the root directory of the FTP process can be changed to be the anonymous FTP user homedirectory. What this means is that, because the new directory (the FTP homedir) is the root, no access what-so-ever is allowed to the rest of the system.
The anonymous user homedirectory may need some special setup done to it ahead of time. For example, you need to recreate a bit of the hierarchy of a real system with in the chrooted environment (like a fake /etc/passwd file and any binaries that might be needed in /bin. Binaries that might be needed are gzip and tar that can be used to archive and compress "on the fly" as files are being downloaded.
The FTP upload scenario is fraught with danger. What uploading means is that an FTP user may perform the STORE command (among other things; aka the put command) to install arbitrary files on the FTP server machine. Unlimited upload servers are a hacker heaven because the upload site can be used to store stolen software or other binaries (like mp3 audio files) without danger to the hacker. (The site then gets advertised on hacker IRC channels...)
I recommend that you do not use this function of FTP unless you absolutely have to. If you do have to allow FTP uploading then there are some things you can do to alleviate the risks.
In general, FTP user access (i.e. normal users, not the anonymous user) is a very bad idea. FTP is totally insecure and requires the use of users' standard Unix passwords! Some FTP servers (notably OpenBSD's ftpd) will allow you to use a One Time Password scheme like skey(1); although even if you set up the OTP (skey) stuff, the user may still use their normal password if they choose to.
A much better alternative to allowing user access is to provide each local user with their own public_ftp directory. The public_ftp directories are then mounted within the chrooted anonymous FTP directory. It is important that this is done in such a fashion that the FTP user doesn't have access to any other parts of the local users' homedirectories.
If you have to allow FTP user access then consider using some sort of FTP proxy host that requires a seperate form of authentication (like Skey). One such proxy is available with the T.I.S. firewall toolkit. I haven't personally set this up, but I understand it to be a royal pain. However, it does offer a secure proxy host setup which can be invaluable, despite the painful configuration.
If you are not running OpenBSD, then consider using the FTP server from Washington University: wu-ftpd. It has many of the same features as the OpenBSD server and has even more configuration options.
Here, I will go over what I did to get FTP running on my home gateway box coatlicue. I am not allowing FTP through my firewall from the outside world at all, so this server is only for internal use. (In particular, I have a housemate who likes to ftp files to the gateway from his macintosh, and then transfer them securely to other machines on the 'net using scp.) Anyway, the result is that I am setting up the ftpd to be both an anonymous server and permit local user access.
First is the question about how ftpd will be started: as a standalone daemon at boot time or as needed out of inetd? Since I think this server will almost never be used I will of course choose to run it out of inetd.
coatlicue% grep ftp /etc/rc.conf
# Set to NO if ftpd is running out of inetd
ftpd_flags=NO # for non-inetd use: "-D"
coatlicue% grep ftp /etc/inetd.conf
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -USll
#tftp dgram udp wait root /usr/libexec/tftpd tftpd -s /tftpboot
coatlicue%
I added the -ll flags to the ftpd invocation in inetd.conf to
provide maximum logging of all ftp activity: I think that every ftp
command gets logged. Note from the ftpd(8) manpage:
...
-l Each successful and failed ftp(1) session is logged using syslog
with a facility of LOG_FTP. If this option is specified twice,
the retrieve (get), store (put), append, delete, make directory,
remove directory and rename operations and their filename argu-
ments are also logged.
...
-S With this option set, ftpd logs all anonymous downloads to the
file /var/log/ftpd when this file exists.
...
So be sure to create the log files and make sure /etc/syslog.conf has
the right stuff:
coatlicue% sudo touch /var/log/ftpd
Password:
coatlicue% grep ftp /etc/syslog.conf
*.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none /var/log/messages
ftp.info /var/log/xferlog
The important line in the /etc/syslog.conf file is the second one.
Keep in mind, regarding syslog, that ftp.info specifies that all
messages that come in for ftp will be logged to the file /var/log/xferlog
if they are of a severity level of info or greater (i.e. pretty
much all the severity levels except 'debug'). Also HUP syslogd
if you have edited the syslog.conf file:
coatlicue% ps aux | grep syslog
tor 13472 0.0 0.3 124 200 p5 S+ 10:41PM 0:00.14 grep syslog
root 15592 0.0 0.2 96 120 ?? Ss 4Apr00 0:52.44 syslogd
coatlicue% sudo kill -1 15592
Then make sure you have an ftp user (the username required by
the OpenBSD ftpd server). Run adduser or whatever.
coatlicue% sudo grep ftp /etc/master.passwd
ftp:*:1003:1003::0:0:anon y mous:/home/ftp:/sbin/nologin
After you run adduser you will definately want to run vipw
and change the password to an asterisk (i.e. "starred-out")
and the shell to /sbin/nologin, as in the above example. Both of these
changes are important for security reasons, and don't affect the
functionality of the anonymous ftp sessions.
After adding the ftp user you need to spend a bit of time setting up what will be the chrooted ftp session environment in the ftp home directory. The ftpd(8) manpage has this to say about it:
In [the anonymous user] case, ftpd takes special measures to restrict the
client's access privileges. The server performs a chroot(2) to the home
directory of the ``ftp'' user. In order that system security is not
breached, it is recommended that the ``ftp'' subtree be constructed with
care, following these rules:
~ftp Make the home directory owned by ``root'' and unwritable
by anyone (mode 555).
~ftp/bin Make this directory owned by ``root'' and unwritable by
anyone (mode 511). This directory is optional unless you
have commands you wish the anonymous ftp user to be able
to run (the ls(1) command exists as a builtin). Any pro-
grams in this directory should be mode 111 (executable only)
~ftp/etc Make this directory owned by ``root'' and unwritable by
anyone (mode 511). The files pwd.db (see pwd_mkdb(8))
and group(5) must be present for the ls command to be
able to produce owner names rather than numbers. The
password field in pwd.db is not used, and should not con-
tain real passwords. The file motd, if present, will be
printed after a successful login. These files should be
mode 444.
~ftp/pub Make this directory mode 555 and owned by ``root''. This
is traditionally where publically accessible files are
stored for download.
So, first I'll do some of the easy stuff:
coatlicue% cd ~ftp
coatlicue% sudo chown root .
Password:
coatlicue% sudo chmod 555 .
coatlicue% sudo mkdir pub etc bin
coatlicue% sudo chmod 511 bin etc
coatlicue% sudo chmod 555 pub
coatlicue% sudo cp /etc/group etc
coatlicue% sudo cp /etc/master.passwd etc
At this point you have to edit the copy of the master.passwd file
that you copy into the ~ftp/etc directory. Specifically, as noted,
star-out or alter the passwords. When you are done, issue the following
incantation (read the manpages, too!):
coatlicue% sudo pwd_mkdb -p -d /home/ftp/etc /home/ftp/etc/master.passwd
To create the actual .db files as recommended in the ftpd manpage.
I also created a motd file. Finally, make sure the etc files
have the right permissions, too:
coatlicue% foreach f (`sudo ls etc`)
foreach? sudo chmod 444 etc/$f
foreach? end
coatlicue% sudo ls -l etc
total 168
-r--r--r-- 1 root ftp 378 May 3 22:59 group
-r--r--r-- 1 root ftp 845 Apr 26 14:35 master.passwd
-r--r--r-- 1 root ftp 93 May 3 23:01 motd
-r--r--r-- 1 root ftp 780 May 3 23:05 passwd
-r--r--r-- 1 root ftp 40960 May 3 23:05 pwd.db
-r--r--r-- 1 root ftp 40960 May 3 23:05 spwd.db
Finally, I need to put a document in the pub directory, so I
can test the server.
coatlicue% ls pub
README
coatlicue%
All right, let's test it out from xibalba:
xibalba % ftp coatlicue
Connected to coatlicue.
220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
Name (coatlicue:tor): anonymous
331 Guest login ok, type your name as password.
Password:
230- Welcome to the Coatlicue FTP Server
230- Please note that all connections and commands are logged
230 Guest login ok, access restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for '/bin/ls'.
total 6
dr-x--x--x 2 ftp ftp 512 Apr 26 14:32 bin
dr-x--x--x 2 ftp ftp 512 May 3 23:05 etc
dr-xr-xr-x 2 ftp ftp 512 Apr 26 14:33 pub
226 Transfer complete.
ftp> cd pub
250 CWD command successful.
ftp> get README
local: README remote: README
200 PORT command successful.
150 Opening BINARY mode data connection for 'README' (68 bytes).
226 Transfer complete.
68 bytes received in 0.0278 secs (2.4 Kbytes/sec)
ftp> quit
221 Goodbye.
xibalba %
Yeah! It's that easy! User access FTP ought to just work,
I don't recommend ever using it unless you have set up the S/Key
stuff. Here is a transcript just in case you don't believe that
it just works:
xibalba % ftp coatlicue
Connected to coatlicue.
220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
Name (coatlicue:tor):
331 Password required for tor.
Password:
230- OpenBSD 2.6 (GENERIC) #287: Thu Oct 21 23:31:48 MDT 1999
230-
230- Welcome to OpenBSD: The proactively secure Unix-like operating system.
230-
230 User tor logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for '/bin/ls'.
total 7010
-rw------- 1 tor wheel 2267 Apr 4 13:25 .Xauthority
-rw-r--r-- 1 tor wheel 17320 Aug 15 1999 .Xdefaults
-rw-r--r-- 1 tor wheel 2701 Oct 24 1999 .alias
-rw-r--r-- 1 tor wheel 2646 Aug 15 1999 .alias.old
-rw------- 1 tor wheel 70 Aug 15 1999 .bash_history
-rw-r--r-- 1 tor wheel 1787 Oct 31 1999 .cshrc
-rwxr-xr-x 1 tor wheel 5111 Aug 15 1999 .dtprofile
...
-rw-r--r-- 1 tor wheel 150 Nov 27 16:50 traffic
226 Transfer complete.
ftp> quit
221 Goodbye.
xibalba %
Here is a quick look at the CS department FTP setup. We use the wu-ftpd mentioned above, running on a *SunOS 4.1.3* box (a SparcStation 5). Most of the setup is similar to what I did for the OpenBSD server. In fact, there are only two things worth noting.
First, the upload directory. In this case the directory is name submissions because it is most frequently used for the submission of research and technical papers:
freestuff % ls -ldg pub/submissions
d-wxrwx--t 2 ftp faculty 512 Apr 4 04:45 pub/submissions/
Notice that the directory is owned and writable by the ftp
user, but not readable. The directory is readable for
the faculty group, however, to facilitate them being able to
retrieve the documents from the submissions directory themselves
(via NFS, not FTP).
Second, is the setup we have for mounting user public_ftp directories. To mount just the public_ftp directory we make use of a feature of traditional NFS. For example, my personal homedir is exported from a machine named fcsk and you can see that with the showmount command:
freestuff % showmount -e fcsk
export list for fcsk:
/tmp_mnt/home/girl cs-all
/tmp_mnt/home/boy cs-all
/tmp_mnt/home/improvement cs-all
/tmp_mnt/home/fcsk cs-all
And, when I log into the machine where out ftp server runs, my
homedir gets mounted normally, as you would expect:
freestuff % cd ~tor
freestuff % pwd
/tmp_mnt/home/fcsk/tor
freestuff % df .
Filesystem kbytes used avail capacity Mounted on
fcsk.cs.colorado.edu:/tmp_mnt/home/fcsk xxx /tmp_mnt/home/fcsk
The trick is that traditional NFS will allow you to mount a subdir
of the exported filesystem instead of the filesystem itself! For example,
the public_ftp subdirectory of a specific user's homedir. The mounts
happen automatically because of a specialized AMD map. Watch what happens
when I cd into the ftp users directory...
freestuff % cd /local/ftp/users
freestuff % ls
baveja@ seidl@
freestuff % cd tor
freestuff % ls
foo/ nlp/ saclass/ tqs-1.0/
freestuff % pwd
/.amd/fcsk/tor
freestuff % cd /local/ftp/users
freestuff % ls
freestuff % ls -l
total 2
lrwxrwxrwx 1 root 19 May 3 23:49 baveja -> /.amd/hobbit/baveja/
lrwxrwxrwx 1 root 18 May 4 00:11 mozer -> /.amd/neuron/mozer/
lrwxrwxrwx 1 root 15 May 3 23:23 seidl -> /.amd/vex/seidl/
lrwxrwxrwx 1 root 14 May 4 00:06 tor -> /.amd/fcsk/tor/
freestuff %
And you can look at the actual mounts like so:
freestuff % mount | grep fcsk
fcsk.cs.colorado.edu:/tmp_mnt/home/fcsk on /tmp_mnt/home/fcsk type nfs ..
fcsk:/tmp_mnt/home/fcsk/tor/public_ftp on /.amd/fcsk/tor type nfs ..
Pretty cool! Here is a sample of the AMD map:
# AMD map for users' public_ftp dirs
#
# This map is built automatically by ftp_registryd
# *Never* edit it by hand, changes _will_ be *lost*
# or you may hose the registry completely.
# If you do, millert will flog you with a clammy noodle.
#
/defaults type:=nfs;fs:=/.amd/${rhost}/${key};opts:=ro,${NFS_BOILERPLATE},\
timeo=${NFS_TIMEO},retrans=${NFS_RETRANS},rsize=${NFS_RSIZE},wsize=${NFS_WSIZE}
millert rhost:=fcsk;rfs:=/tmp_mnt/home/improvement/millert/public_ftp
mcginley rhost:=fcsk;rfs:=/tmp_mnt/home/girl/mcginley/public_ftp
tor rhost:=fcsk;rfs:=/tmp_mnt/home/fcsk/tor/public_ftp
...
If you are curious, despite the fact that the ftp session operates
in a chrooted environment, AMD still controls the mountpoint ~ftp/users.
There is one caveat however, the symlink that AMD creates must
point somewhere within the chrooted environment. You can see
that AMD makes a symlink pointing to something like /.amd/fcsk/tor
and (ahead of time) we have made a symlink as follows (keep
in mind that the chrooted environment is /local/ftp)
freestuff % ls -lad /.amd
lrwxrwxrwx 1 root 14 Mar 31 1999 /.amd -> local/ftp/.amd
Pretty clever! So the mountpoint really ends up
being /local/ftp/.amd/fcsk/tor, for example. Fun with symlinks
and chroot...
The maintenance of system files on only a handful of machines is trivial enough. However, when the number of machines gets into the hundreds, such manual methods simply don't scale. One program that can alleviate this problem is called rdist. Rdist is a client/server based program that uses the remote shell interface (i.e. rpc - Remote Procedure Call). The client is the machine initiating the rdist, the sender. The server is the receiver. The server side of the process must run a daemon program called rdistd which usually is invoked from inetd via shell - that is, the client uses 'rsh' to startup the rdistd daemon on the receiving host.
Using rdist in a networking environment requires that the host from whom files will be 'disted' to be trusted by all of the hosts who will receive the dists. The trusted host is often called the 'master' host, or the 'admin' host. The other machines are often just called 'clients'. Note that this exactly the opposite notion of master/client than the names of the rdist and rdistd commands imply.. just to be confusing, I guess.
You must ensure that the recipient hosts have the following:
Remember that one 'BSD and RedHat you can control how inetd responds based on IP address - read the manpages for details.
Let's first look at a simple example from the saclass-N machines.
I set up a simple distfile to automate the distribution of
the /etc/sudoers file. In this case, the machine saclass-1 is
the master, trusted, machine, and the other three receive the dists.
The setup issues on saclass-2, an OpenBSD box.
First make sure shell is enabled in /etc/inetd.conf:
saclass-2 % grep shell /etc/inetd.conf
shell stream tcp nowait root /usr/libexec/rshd rshd -L
Yup, there it is, and UNcommented.
(Note that it will be commented out by default!)
Next, make sure that 'saclass-1' appears in root's .rhosts file:
saclass-2 % sudo cat ~root/.rhosts
saclass-1.cs.colorado.edu
The setup issues on saclass-3 and -4 differ slightly, as
they are RedHat Linux boxes. One difference may be that you are using
xinetd instead. Another (important either way)
difference is the arguments for the 'shell' entry in inetd.conf:
saclass-4 % grep shell /etc/inetd.conf
shell stream tcp nowait root /usr/sbin/tcpd in.rshd -h
Notice the -h argument. This is not present in the default entry
(which is actually a Good Thing, as it disables root access...)
Now, on saclass-1 we probably want to make sure that root's .rhosts file
is not present or empty and read-only. We also should turn off the
remote shell service in /etc/inetd.conf. Two simple security precautions.
To fully automate the procedure, we need two things: a distfile with rules describing what files will be disted and to whom, and we need a crontab entry to periodically run rdist for us.
Here is the crontab entry:
saclass-1 % sudo crontab -l | grep rdist
1,16,31,46 * * * * /usr/local/sbin/rdist_sudoers
The above crontab entry invokes a script called rdist_sudoers every 15 minutes.
The script is just a simple wrapper around rdist. It looks like this:
saclass-1 % cat /usr/local/sbin/rdist_sudoers
#!/bin/sh
/usr/bin/rdist -f /usr/local/etc/sudoers
This wrapper is so simple it is hardly worth using. A better wrapper
script should verify the invoking user, and send mail if there is a failure.
And lastly, here is the distfile itself:
saclass-1 % cat /usr/local/etc/sudoers
CLIENTS = ( saclass-2 saclass-3 saclass-4 )
FILES = ( /etc/sudoers )
( ${FILES} ) -> ( ${CLIENTS} )
install;
The above distfile is also very simple, but illustrates the basic
functionality of the distfile concept. The first line is
defining a list of machine names; the second line, a list of files.
The final two lines are an actual 'dist' rule. These rules have
a basic syntax like so:
( <file-list> ) -> ( <machine-list> )
<install-option>;
...
The syntax in english says: "take this list of files and distribute them to
this list of machines."
If you invoke the rdist by hand it looks like this:
saclass-1 % sudo rdist -f /usr/local/etc/sudoers
saclass-2: updating host saclass-2
saclass-4: updating host saclass-4
saclass-3: updating host saclass-3
saclass-4: /etc/sudoers: updating
saclass-4: updating of saclass-4 finished
saclass-2: /etc/sudoers: updating
saclass-2: updating of saclass-2 finished
saclass-3: /etc/sudoers: updating
saclass-3: updating of saclass-3 finished
You may use the install-options section to perform special commands
if you need to. For example, if you were to distribute the sendmail
/etc/mail/aliases file to all of your machines, you would want to
rebuild the alias database file also. You could setup an dist rule
to do this for you like so:
( /etc/mail/aliases ) -> ( ${CLIENTS} )
install;
special /etc/mail/aliases "/usr/sbin/sendmail -bi";
This would dist the aliases file to the machine and then run the 'newaliases'
(actually, I'm using sendmail directly - newaliases is just "sendmail -bi")
command on that machine for each machine in the CLIENTS list. The commands specified in
the double-quotes can be any arbitrary bourne shell code. For example, if you
were disting to both BSD and RedHat boxes, then the sendmail command lives in
different places... here is one solution:
( /etc/mail/aliases ) -> ( ${CLIENTS} )
install;
special /etc/mail/aliases "if [ -f /usr/sbin/sendmail ]; then /usr/sbin/sendmail -bi; \
else /usr/lib/sendmail -bi; fi";
Please note that the quoted shell commands must be ; (semi-colon) seperated and must
be on one line!
(in the example above, I split it over two lines for visual readability.)