Despite the recent increase in the deployed footprint of encrypted services such as SSH, FTP services are still sometimes necessary. Many clients (most notably certain Redmond-based operating systems) do not ship with an SSH client at all, which forces many administrators to accept the risks of cleartext FTP transfers. This section will discuss the configuration of the WUFTPd FTP server package shipped with Red Hat7.3 for individual file transfers and anonymous file access in a secure manner. Fortunately, the Washington University FTP daemon has gotten progressively more intelligent and useful over the years , and it now ships with a fairly secure default configuration from Red Hat. We'll edit this configuration file to enable secure user FTP sessions, then again for anonymous file transfers.
By default, WUFTPd comes pre-configured to chroot all users into their home directories automatically. Even better, this action is done by the daemon and does not require creating additional binary or library directories on the server in order to function: it just works. In order to properly secure this, though, we'll need to tweak the main FTP configuration file, /etc/ftpaccess .
/etc/ftpaccess (Changes are marked in bold , comments in italics )
Don't allow system accounts to login over FTP. Comment out the right for the FTP user to login over FTP ”that's only needed for anonymous transfers
deny-uid %-99 %65534- deny-gid %-99 %65534- # allow-uid ftp # allow-gid ftp
Chroot all users by default
guestuser *
List any users you wish to grant "real" privileges to (i.e. that should not be chrooted ) here
realuser <ftp administrators, etc.>
We don't need an explicit chroot group : all users will be chrooted!
# guestgroup ftpchroot
Set your email address
email ftpadmin@ftpserver.mydomain.com
Permit only 2 failed logins before terminating the session
loginfails 2
Set the welcome message to something we can control and eliminate from directory listings
message /.ftpwelcome.msg login
Do not allow on-the-fly tarring and compressing
compress no all tar no all
Prevent certain actions by anonymous and/or guest users. Explicitly list permissions for everyone.
chmod no guest,anonymous delete no anonymous overwrite no anonymous rename no anonymous umask no real,guest,anonymous delete yes real,guest overwrite yes real,guest rename yes real,guest
Log commands and transfers to and from the server (this will not log passwords unless the user types one as a command by mistake).
log commands real,anonymous,guest log transfers anonymous,guest,real inbound,outbound
Mark certain files as non-retrievable
noretrieve .notar noretrieve .ftpwelcome.msg
Set a secure path filter to weed out evil files
path-filter guest,anonymous /etc/pathmsg ^[-A-Za-z0-9_\.]*$ ^\. ^-
Shorten the greeting string so as not to provide the server version
greeting terse
Use secure default umasks for everyone
defumask 0377 defumask 0177 real defumask 0133 guest
Finally, we need to make some modifications to our users' home directories. Let's set up a user who will only be permitted to FTP files in and out of his directory, but nothing more.
useradd -d /home/user -s /sbin/nologin -m user passwd user # Set the user's password cd /home/user cp /etc/issue.net /home/user/.ftpwelcome.msg # You have a security banner in /etc/issue.net, right? chown root:root /home/user/.ftpwelcome.msg chmod 444 /home/user/.ftpwelcome.msg # Keep the user from tampering with the message or chattr +i /home/user/.ftpwelcome.msg # disabling it. for file in .rhosts .shosts .netrc .forward ; do # Script the creation and lockdown touch $file # of some sensitive files. chown root:root $file chmod 0 $file chattr +i $file done rm .bash* .gtk* # Since he'll never login, he'll never need shell files
Now test the server:
[user@otherhost user]$ ftp 192.168.1.20 Connected to 192.168.1.20. 220 FTP server ready. User (192.168.1.20:(none)): luser 331 Password required for luser. Password: 230-### WARNING ### 230- 230-This automated information system is for the exclusive use of 230-Systems Engineering personnel. Use of this system 230-without privilege or in excess of granted authority is forbidden, and 230-may be subject to civil and criminal penalties up to and including the 230-fullest extent permitted by law. 230- 230-Users accessing this system are subject to having their actions 230-monitored and recorded at any time. Use or access of this system in 230-any fashion constitutes expressed knowledge and acceptance of this 230-policy. 230- 230-### WARNING ###230- 230 User luser logged in. Access restrictions apply. ftp> pwd 257 "/" is current directory. ftp> ls -la 200 PORT command successful. 150 Opening ASCII mode data connection for directory listing. total 24 drwx--------- 2 2501 2501 4096 Aug 18 22:39 . drwx--------- 2 2501 2501 4096 Aug 18 22:39 .. --------------- 1 root root 0 Aug 18 22:39 .forward -r---r---r--- 1 root root 554 Aug 18 22:38 .ftpwelcome.msg --------------- 1 root root 0 Aug 18 22:39 .netrc --------------- 1 root root 0 Aug 18 22:39 .rhosts --------------- 1 root root 0 Aug 18 22:39 .shosts 226 Transfer complete. ftp: 455 bytes received in 0.00Seconds 455000.00Kbytes/sec. ftp> put foo.txt 200 PORT command successful. 150 Opening ASCII mode data connection for foo.txt. 226 Transfer complete. ftp: 479 bytes sent in 0.00Seconds 479000.00Kbytes/sec. ftp> del foo.txt 250 DELE command successful. ftp> mkdir foo 257 "/foo" new directory created. ftp> rmdir foo 250 RMD command successful. ftp> cd / 250 CWD command successful. ftp> ls -a 200 PORT command successful. 150 Opening ASCII mode data connection for directory listing. . .. .forward .ftpwelcome.msg .netrc .rhosts .shosts 226 Transfer complete. ftp: 60 bytes received in 0.00Seconds 60000.00Kbytes/sec. ftp> cd ../../../../../etc 550 ../../../../../etc: No such file or directory. ftp> bye 221-You have transferred 466 bytes in 1 files. 221-Total traffic for this session was 2347 bytes in 1 transfers. 221-Thank you for using the FTP service on ftpserver.mydomain.com. 221 Goodbye.
To enable an anonymous FTP server, we only require a little further tweaking of the configuration file, and the careful creation of an FTP server root directory. Anonymous FTP servers should be handled like live snakes : treat them carefully , don't trust them fully, and keep them as far away from sensitive areas as possible! Thankfully, the combination of a good default ftpaccess file and the ease of configuring this latest WUFTPd means that anonymous FTP services can be configured with a minimum of heartburn.
First, we'll need to add some information to /etc/ftpaccess , in addition to the changes made above. Both sets of changes have been presented below, for simplicity's sake, but be careful to enter all of these changes to keep things nice and secure.
/etc/ftpaccess
Don't allow system accounts to login over FTP.
deny-uid %-99 %65534- deny-gid %-99 %65534-
Chroot all users by default
guestuser *
List any users you wish to grant "real" privileges to (i.e. that should not be chrooted) here
realuser <ftp administrators, etc.>
We don't need an explicit chroot group: all users will be chrooted!
# guestgroup ftpchroot
Set your email address
email ftpadmin@ftpserver.mydomain.com
Permit only 2 failed logins before terminating the session
loginfails 2
Set the welcome message to something we can control and eliminate from directory listings
message /.ftpwelcome.msg login
Do not allow on-the-fly tarring and compressing
compress no all tar no all
Prevent certain actions by anonymous and/or guest users. Explicitly list permissions for everyone.
chmod no guest,anonymous delete no anonymous overwrite no anonymous rename no anonymous umask no real,guest,anonymous delete yes real,guest overwrite yes real,guest rename yes real,guest
Log commands and transfers to and from the server (this will not log passwords unless the user types one as a command by mistake).
log commands real,anonymous,guest log transfers anonymous,guest,real inbound,outbound
Mark certain files as non-retrievable
noretrieve .notar noretrieve .ftpwelcome.msg
Set up permissions for anonymous users within their file structure. Anonymous users may not upload files anywhere except specifically -configured areas.
upload /usr/local/ftp * no
Anonymous users may upload files to their incoming directory, but the files will be immediately owned by a different user and group on the server and changed to read-only for members of that group. This will prevent the anonymous users from listing the contents of the incoming directory, preventing them from turning it into a wAreZ storehouse. They won't be able to retrieve anything from that directory either, and can't create subdirectories.
upload /usr/local/ftp/incoming yes ftpusers ftpusers 0040 nodirs
Set a secure path filter to weed out evil files
path-filter guest,anonymous /etc/pathmsg ^[-A-Za-z0-9_\.]*$ ^\. ^-
Shorten the greeting string so as not to provide the server version
greeting terse
Use secure default umasks for everyone
defumask 0377 defumask 0177 real defumask 0133 guest
Next, we'll need to create the anonymous file directory. Mercifully, we no longer have to create binary or library directories, just file storage areas. Be careful with the permissions in this area! First, we'll need a user and group with no privileges: they'll wind up owning uploaded files, which "real" users on the system (who have been added to that group) can login through SSH and copy to other areas of the server to retrieve:
useradd -d /usr/local/ftp -s /dev/null ftpusers passwd -l ftpusers
Now we can create the storage tree in /usr/local/ftp :
mkdir /usr/local/ftp cd /usr/local/ftp mkdir incoming mkdir pub chmod 755 pub chown ftp:ftpusers incoming # Note the "ftp" user here: that's so the anonymous user can write to this directory. chmod 0370 incoming # Grant write and execute privileges for storage, but no reads chown root:root pub # /pub will be a read-only file retrieval area cp /etc/issue.net ./.ftpwelcome.msg # You have a security banner in /etc/issue.net, right? chown root:root ./.ftpwelcome.msg chmod 444 ./.ftpwelcome.msg # Keep the user from tampering with the message or disabling it. chattr +i ./.ftpwelcome.msg for file in .rhosts .shosts .netrc .forward ; do # Script the creation and lockdown touch $file # of some sensitive files. chown root:root $file chmod 0 $file chattr +i $file done rm .bash* .gtk* # Since he'll never login, he'll never need shell files
Finally, change the home directory for the ftp user in /etc/passwd to the new FTP server directory at /usr/local/ftp :
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
becomes
ftp:x:14:50:FTP User:/usr/local/ftp:/sbin/nologin
Now you can test the server:
[user@other user]# ftp 192.168.1.20 Connected to 192.168.1.20 (192.168.1.20). 220 FTP server ready. Name (192.168.1.20:user): anonymous 331 Guest login ok, send your complete e-mail address as password. Password: 230-### WARNING ### 230- 230-This automated information system is for the exclusive use of 230-Systems Engineering personnel. Use of this system 230-without privilege or in excess of granted authority is forbidden, and 230-may be subject to civil and criminal penalties up to and including the 230-fullest extent permitted by law. 230- 230-Users accessing this system are subject to having their actions 230-monitored and recorded at any time. Use or access of this system in 230-any fashion constitutes expressed knowledge and acceptance of this 230-policy. 230- 230-### WARNING ### 230- 230 Guest login ok, access restrictions apply. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 227 Entering Passive Mode (10,1,1,47,87,244) 150 Opening ASCII mode data connection for directory listing. total 16 d-wxrwx--- 2 14 2500 4096 Aug 18 22:07 incoming drwxr-xr-x 2 root root 4096 Aug 18 22:02 pub 226 Transfer complete. ftp> mkdir asdf 550 asdf: Permission denied on server. (Upload dirs) ftp> cd pub 250 CWD command successful. ftp> mkdir asdf 550 asdf: Permission denied on server. (Upload dirs) ftp> ls 227 Entering Passive Mode (10,1,1,47,179,115) 150 Opening ASCII mode data connection for directory listing. total 8 -rw-r---r--- 1 root root 3859 Aug 18 22:02 osshChroot-3.4.diff 226 Transfer complete. ftp> get osshChroot-3.4.diff local: osshChroot-3.4.diff remote: osshChroot-3.4.diff 227 Entering Passive Mode (10,1,1,47,236,173) 150 Opening BINARY mode data connection for osshChroot-3.4.diff (3859 bytes). 226 Transfer complete. 3859 bytes received in 0.000342 secs (1.1e+04 Kbytes/sec) ftp> del osshChroot-3.4.diff 553 osshChroot-3.4.diff: Permission denied on server. (Delete) ftp> cd ../incoming 250 CWD command successful. ftp> ls 227 Entering Passive Mode (10,1,1,47,205,141) 150 Opening ASCII mode data connection for directory listing. total 0 226 Transfer complete. ftp> put osshChroot-3.4.diff local: osshChroot-3.4.diff remote: osshChroot-3.4.diff 227 Entering Passive Mode (10,1,1,47,242,244) 150 Opening BINARY mode data connection for osshChroot-3.4.diff. 226 Transfer complete. 3859 bytes sent in 0.0105 secs (3.6e+02 Kbytes/sec) ftp> ls 227 Entering Passive Mode (10,1,1,47,9,59) 150 Opening ASCII mode data connection for directory listing. total 0 226 Transfer complete. ftp> ls -a 227 Entering Passive Mode (10,1,1,47,155,95) 150 Opening ASCII mode data connection for directory listing. total 0 226 Transfer complete. ftp> ls -la 227 Entering Passive Mode (10,1,1,47,48,107) 150 Opening ASCII mode data connection for directory listing. total 0 226 Transfer complete. ftp> get osshChroot-3.4.diff local: osshChroot-3.4.diff remote: osshChroot-3.4.diff 227 Entering Passive Mode (10,1,1,47,67,94) 550 /incoming/osshChroot-3.4.diff is marked unretrievable ftp> mkdir asdf 550 asdf: Permission denied on server. (Upload dirs) ftp> exit 221-You have transferred 7718 bytes in 2 files. 221-Total traffic for this session was 10482 bytes in 2 transfers. 221-Thank you for using the FTP service on ftpserver.mydomain.com. 221 Goodbye. [user@other user]#
The words "NFS" and "security" are not usually used in the same sentence together, unless it's a discussion of the lack of the latter in the former. There are times, however, when NFS is the simplest answer to solving a problem: sharing filesystems between multiple servers is never a simple problem, and NFS is sometimes the path of least resistance. The following section should assist administrators in securing this service as much as possible without vast complication.
We'll discuss two possible configurations: one featuring a transient filesystem that is only mounted when needed, and one featuring a more permanent filesystem mount, such as a shared set of home directories or system library or binary directories for thin clients.
Before attempting any sort of file sharing from an NFS server, it is a good idea to take some basic steps to secure the server's configuration. One major problem with NFS is its reliance on RPC-based services: rather than being assigned to a fixed port, RPC services are assigned a port randomly (or semi-randomly, or in some cases, not randomly at all) when they are initiated, by the RPC portmapper daemon. Clients wishing to connect to those services will first contact the portmapper daemon to inquire to which port the needed service has been assigned. Among other things, this plays havoc with firewalls, which rely on services being assigned a particular port time and again, which can make firewalling NFS services very difficult.
Fortunately, Red Hat's NFS implementation reduces this headache considerably through the use of some thoughtful configuration options: with the following quick changes, we can make NFS as firewall-friendly as possible.
First, we need to configure the portmapper daemon. It is always assigned the same port (TCP and UDP 111), so we don't need to worry about fixing that, but we do need to restrict access to it. Since this will be the gateway to the NFS services on the server, we need to carefully control to whom we grant access. By default, the portmapper daemon on Red Hat Linux comes compiled with support for Wietse Venema's TCP wrappers, which allows us to control access to it using a pair of configuration files. In /etc/ hosts .deny , we'll first set a default-deny policy for the portmapper:
/etc/hosts.deny portmap: ALL
Now we'll configure /etc/hosts.allow to permit access to the portmapper from trusted internal machines. Add IP addresses into this file to permit NFS clients access to the portmapper, being careful to list specific IPs rather than subnets, where possible. Below, we've granted access only to the NFS client at IP address 10.1.2.3.
/etc/hosts.allow portmap: 10.1.2.3
The mount daemon (mountd) actually implements NFS mount requests : when a client wishes to mount a filesystem over NFS, it sends a MOUNT request to mountd to initiate the process, who verifies the request against the list of exported filesystems and returns a filehandle of the filesystem if the request is approved.
Mountd is an RPC service, so the first thing to do is to lock in the port to which it will be assigned. Anticipating this desire , Red Hat has configured a simple way to do this by adding the information to a configuration file rather than having to edit the startup file for this service by hand. First, choose a port for the mount daemon: it can be any port number higher than 1024, with the default choice being 2050 most of the time. Once you've selected your port, edit /etc/sysconfig/network as follows (we've used 2050 as an example):
/etc/sysconfig/network MOUNTD_PORT=2050
On Red Hat Linux, mountd has also been compiled with support for TCP wrappers, so this service can be granted additional security by permitting access only from selected clients. This prevents an NFS problem in which clients could bypass restrictions on the portmapper and mount a filesystem by sending the request directly to mountd if they could figure out on what port mountd was running. To implement this, edit /etc/hosts.deny and /etc/hosts.allow again and add to the bottom the following lines (as an example, we've again granted access only to the NFS client at IP address 10.1.2.3):
/etc/hosts.deny mountd: ALL /etc/hosts.allow mountd: 10.1.2.3
The NFS daemon (nfsd) is a sort of go-between, shuttling information back and forth between the userland space and the kernel module (nfsd.o) actually implementing NFS under Linux. Like mountd, nfsd is an RPC service, so it has no fixed port, and unlike mountd, it has not been compiled with support for TCP wrappers nor does it have a convenient shortcut in the system configuration files for pre-selecting a port. However, we can pre-select the port on it by editing the startup script ( /etc/init.d/nfs ) by hand and adding the following information:
/etc/init.d/nfs
Find this block:
echo -n $"Starting NFS daemon: " daemon rpc.nfsd $RPCNFSDCOUNT
And change it to read thus (using 2049 as our pre-selected port for nfsd):
echo -n $"Starting NFS daemon: " daemon rpc.nfsd -p 2049 $RPCNFSDCOUNT
The remote quota daemon ( rquotad ) is responsible for answering clients' queries about user quotas for exported NFS filesystems. That is, when a client attempts to write to an NFS filesystem, it will first inquire of the quota daemon (if the server has quotas active for that filesystem) whether the client has sufficient quota to issue the write. Rquotad will then check the local quotas for that user and return that information to the client. Unfortunately, in addition to lacking TCP wrappers support, rquotad cannot be fixed to a specific port. If you wish to tie user quotas to NFS, you will need to plan for this, since rquotad cannot be further secured.
On the other hand, if you are not using quotas, there is no reason to run rquotad, and you can deactivate it without having an impact on your NFS filesystems. To do so, edit the NFS startup script ( /etc/init.d/nfs ):
/etc/init.d/nfs
Comment out the following blocks in this file to deactivate rquotad:
if [ -x /usr/sbin/rpc.rquotad ] ; then echo -n $"Starting NFS quotas: " daemon rpc.rquotad echo fi if [ -x /usr/sbin/rpc.rquotad ] ; then echo -n $"Stopping NFS quotas: " killproc rpc.rquotad echo fi if [ -x /usr/sbin/rpc.rquotad ] ; then status rpc.rquotad fi
You'll notice that all of these blocks check to see if rpc.rquotad is executable (using the -x flag) before running these commands. One possible way of deactivating rquotad is to remove the executable bits from it using chmod ( chmod a-x /usr/sbin/rpc.rquotad would work). While this would deactivate it, an RPM update to quota RPM (or a well-meaning administrator!) would likely restore those executable privileges, thus inadvertently reactivating the daemon. If you've really decided not to use quotas over NFS, commenting those blocks will help guarantee that the service stays deactivated until you choose to activate it. Obviously, if the service is not needed, you should uninstall it to keep it from being a liability to the system in the future: a quick ˜rpm -e quota will accomplish this.
Securing the client is relatively simple: it will only require the portmapper. The mount command will handle the necessary NFS module activations when called upon to mount a filesystem over NFS. Since the client will be running the portmapper, however, this should be secured in the same manner as the server's, restricting inbound connections to only those necessary.
In this example, we'll present a sample configuration for a secured NFS mount between a client and server which would be mounted manually by administrators. This would include shared directories that contain system patches, for example, so that a central patch repository could be remotely mounted to patch servers and then unmounted when not needed. Since the directory containing the patches will only be read by the client and should not be altered , we can export this filesystem read-only. We can also export the filesystem using "squashing", an option that maps UIDs and GIDs on the client to corresponding UIDs and GIDs on the server. Commonly, this is done to the root account, so that the remote client's root account is not automatically granted root-level privileges to the filesystems on the server. In this case, however, we only need the right to read the patches, so we'll export the filesystem with complete squashing: we'll create an unprivileged user on the server who can only read the patches, and map all remote UIDs to that user, reducing all of the client's privileges accordingly . NFS also allows us to export the filesystem to a specific client or group of clients: never export a filesystem to the world! We'll restrict access to the patches share to a local, internal subnet: 10.1.1.0/24, e.g.
Linux offers some convenient extra tweaks to NFS to tighten security a little: the "hide" feature, enabled by default, means that a filesystem mounted within a shared filesystem (such as having /usr and /usr/local on separate disk partitions) is not automatically shared: the server must share that secondary filesystem separately, and the client must mount it separately. In addition, the "secure" feature, also enabled by default, requires that NFS mount requests originate from a privileged port, helping to ensure that the user making the remote mount request is root or has root privileges. This isn't a foolproof determinant, but every little bit helps.
On the Server
Create the patch directory
mkdir /local/patches
Create the unprivileged user and group
groupadd -g 1500 patches useradd -u 1500 -g patches -d /local/patches -s /dev/null patches
Edit /etc/exports to configure the share
/etc/exports /local/patches 10.1.1.0/24(ro,secure,hide,all_squash,anonuid=1500,anongid=1500)
Ensure that the NFS services are running on the server
/etc/init.d/portmap start /etc/init.d/nfs start /etc/init.d/nfslock start
Export all configured filesystem shares (-a), using verbose output (-v)
/usr/sbin/exportfs -va
Copy patches into
/local/patches
On the Client
Ensure the portmapper is running
/etc/init.d/portmap start
Create the mount point
mkdir /nfsmount/patches
Mount the remote filesystem from the server at 10.1.1.50
/bin/mount -t nfs 10.1.1.50:/local/patches /nfsmount/patches
The example being explored here is a filesystem that would be mounted at boot off of a central fileserver. Frequently, this is done with user home directories. Since the users will need individual access to their directories, we cannot employ complete squashing as we did in the previous example. Instead, we'll be sure to use root squashing. In order to do this, you must be careful to synchronize UIDs between the clients and the server. Since access is granted by numerical UID and not by username, a user with a different UID on the client and the server would not have access rights to her own directory, and might (even worse ) have complete access to someone else's entirely!
On the Server
Create the users for whom you'll want to grant access, and synchronize their UIDs with the client. If the users will not ever login to the NFS server directly, they can be granted user accounts with null shells (/dev/null or /bin/false or the like), since that account information will then only be used for mapping NFS privileges. We can at least restrict the access to this filesystem to the local LAN (as is almost always a good idea for security), and we can employ root squashing to prevent root-level breaches.
Edit /etc/exports to configure the share
/etc/exports /home 10.1.1.0/24(rw,secure,hide,root_squash)
Ensure that the NFS services are running on the server
/etc/init.d/portmap start /etc/init.d/nfs start /etc/init.d/nfslock start
Export all configured filesystem shares (-a), using verbose output (-v)
/usr/sbin/exportfs -va
On the Client
One extra piece of security checking to be performed: the client should mount the filesystem as an untrusted volume. This means mounting it without SUID files (nosuid), without devices (nodev) and preferably without executables, to prevent the server from being granted additional privileges on the client. The first two options are particularly important: without them, an attacker with access to the NFS server could insert a SUID shell or compromised device into the shared filesystem and be automatically granted privileges on the other filesystems. Although we've enabled root squashing, remember that there is no squashing for users such as bin or daemon, which are potentially just as dangerous to the client as root access!
Ensure the portmapper is running
/etc/init.d/portmap start
Test connectivity by mounting the remote filesystem from the server at 10.1.1.50
/bin/mount -t nfs 10.1.1.50:/home /home
Configure /etc/fstab to mount the filesystem automatically
/etc/fstab: 10.1.1.50:/home /home nfs nosuid,nodev,noexec 0 0
As much as many Unix administrators revile it, Microsoft's Windows family of operating systems are a fact of modern life at most companies. Fortunately, the interoperability of Unix and Windows hosts is alive and well, thanks both to considerable hard work from open standards bodies such as the IETF, and thanks to programs like Samba. Samba, in the words of its creators , "is an Open Source/Free Software suite that provides seamless file and print services to SMB/CIFS clients." (http://us2.samba.org/samba/samba.html).
SMB/CIFS is a standard developed by Microsoft to offer shared file and print services; thanks to the hard work of the Samba development team, Unix hosts can join in the CIFS fun as clients and as servers, even to the point of masquerading as Windows NT Domain Servers for an entire network of Windows hosts, none of whom will notice the difference.
This section eschews a general configuration discussion of Samba, and focuses on securing Samba on Red Hat Linux 7.3, using the supplied Red Hat packages. We will configure Samba as a server to share files and printers securely, and as a client.
Configuring Samba as a server is fairly simple, once you have the packages for Samba installed. First, decide what filesystems and/or printers you will share to other hosts. Then follow these instructions. For this example, we'll configure a server that will share out user home directories and its printers for its local users. The server will live at IP 192.168.1.20, and will permit IPs in the 192.168.1 network to mount its shares. To increase the security of this configuration, the server will not be part of a domain, but will instead use a local password file for users, who will not be granted command-line access to the server.
Install the Samba packages
rpm -ivh samba-2.2.3a-6.i386.rpm rpm -ivh samba-common-2.2.3a-6.i386.rpm
You'll need to assemble some information:
Your NT domain name or workgroup name:
List of hosts or networks to grant access to this server's shares:
IP of NT domain server, if applicable :
Edit the main Samba configuration file, /etc/samba/smb.conf (changes excerpted and highlighted in bold, with comments in italics ):
/etc/samba/smb.conf # workgroup = NT-Domain-Name or Workgroup-Name # Set this field to your NT domain name or the name of your Windows Workgroup workgroup = Mygroup # Server string is the equivalent of the NT Description field # Change this string to something innocuous, per your organization's standards. # This information will show up in the "Network Neighborhood" browser for users on the # network. server string = Home directory server # Set the list of hosts allowed to connect to this one for services # Be sure to use only IP addresses in this list: hostnames can be spoofed. # The following are all valid IPs for this list: # 192.168.1. would choose all IPs starting with 192.168.1. # 127. would choose anything on the loopback network (e.g. 127.0.0.1) # 192.168.1.47 would choose only this host hosts allow = 192.168.1. # Server security level: # This will set the method by which Samba authenticates users for shares. Do NOT set this # to "share", as this can allow remote clients to mount shares by only sending a username # for access. # Set this to "user" (as is the default) if you are a standalone server, not part of an NT # domain. # If this machine is part of an NT domain, use smbpasswd to add it to the domain, and then # set this value to "domain" to authenticate against the domain server. security = user # Password Level should be set to zero: unless you're using Windows 95 or 98, current Windows # versions can handle properly encoding password strings. Win95, Win98, and Windows for # Workgroups had a habit of sending passwords in all-upper-case letters, which would cause # password checks to fail unless you set this parameter to have the server try setting # various letters in the password to lower-case. A similar thing happens with the username # and older DOS-based clients. password level = 0 username level = 0 # Enable password encryption, to be stored in the smbpasswd file. Fortunately, Red Hat uses # the right behavior by default. encrypt passwords = yes smb passwd file = /etc/samba/smbpasswd # Commenting the following lines prevents synchronization of Unix and SMB passwords, which # in this case is what we want, to keep the two databases separate. We're going to lock # the local user accounts and only grant Samba access. unix password sync = no # passwd program = /usr/bin/passwd %u # passwd chat = *New*password [etc.] pam password change = no # Instruct Samba to map NT users to local Unix accounts using this file username map = /etc/samba/smbusers # Do not have Samba act as a domain logon server for Windows 95 workstations domain logons = no # Now we define the shares # Here are the home directories [homes] comment = Home Directories # Do not list these shares without authentication, e.g. in "Network Neighborhood" browseable = no writable = yes # User accounts are normally valid... valid users = %S # ...unless they appear in this list. Note the use of "@wheel" to designate anyone # in the "wheel" group. invalid users = root bin daemon adm lp sync halt shutdown mail news uucp operator \ games gopher ftp nobody vcsa mailnull ntp rpc xfs gdm rpcuser nfsnobody nscd pcap @wheel # Set the default umask create mode = 644 # Set the default permissions mode for shared directories directory mode = 755 # Here are the printer shares [printers] comment = Shared Printers path = /var/spool/samba # Do not list printer shares without authentication, e.g. in "Network Neighborhood" browseable = no # Users must be authenticated to use these printer sguest ok = no # Users may not remove or disable these printers writable = no printable = yes
Create a user on the Samba server
First, we'll create the user, with a locked shell
useradd -u 1500 -d /home/user -s /dev/null -m user
Next we can lock the user's local password, and set the Samba password, which will be stored in Samba's separate password database, /etc/samba/smbpasswd
passwd -l user smbpasswd -a user [Enter a password for this user to authenticate for Samba shares]
Start up the Samba services, and you should be able to map a drive as that user from a Windows machine on the network.
/etc/init.d/smb start
Samba Client
Next, we'll mount a share from a Windows server on the same network, using smbmount , then configure it to mount at boot.
Check that you can mount the share from the command line. For our example, the server will be named saturn, at IP 192.168.1.20, with a client named mercury at IP 192.168.1.50. We'll mount a shared directory to a local directory named /local/samba on mercury. To ease our configuration a little, we'll add saturn to the hosts file on mercury, so we can locate it by name quickly.
[root@mercury root]# echo "192.168.1.20<tab>saturn" >> /etc/hosts [root@mercury root]# echo >> /etc/hosts [root@mercury root]# mount -t smbfs -o username=user,workgroup=MYGROUP \ //saturn/shared /local/samba Password: <Enter password> [root@mercury root]# ls /local/samba somefiles somemorefiles someotherfiles [root@mercury root]# umount /local/samba
Next, we'll secure the mount as much as we can: we'll create an unprivileged user and corresponding group to own the files in the directory, and set the mount to be group-accessible only. Any users who need access to these files should be added to the group.
useradd -u 5000 -d /local/samba -s /dev/null smbowner passwd -l smbowner
Unfortunately, since the mount point requires authentication, there is no way for the client to create the mount without entering a password of some kind. Since /etc/fstab needs to be world-readable, we'll instead store the credentials for this mount in a file within root's home directory, and make them readable only by root. You can also opt to mark the mount point as not automatically mounted at boot time ( noauto ), and mount it by hand when you reboot, entering the password at the console or over a secure login session. This is more secure, but means that unattended reboots will make the filesystem vanish until someone connects to the server and manually mounts it.
[root@client root]# cat >> /root/.smbmount username = NTUser # Make these values very secure and don't make them the same as password = NTPassword # any other credentials for any other server! [ Press <Ctrl>-D ] [root@client root]# chmod 400 /root/.smbmount [root@client root]# chown root /root/.smbmount [root@client root]# chattr +i /root/.smbmount
Edit /etc/fstab and set up the mount options
/ etc / fstab [...] # The following should be all on one line //saturn/shared /local/samba smbfs credentials=/root/.smbmount,workgroup=MYGROUP \ uid=smbowner,gid=smbowner 0 0
In order for your filesystem to mount automatically at boot, you either have to hack /etc/rc.d/rc.sysinit or else run the netfs service on your machine, which automatically mounts any network-based filesystems configured in /etc/fstab . Without that service, Samba filesystems will not be mounted automatically. To turn it on, run this command:
/sbin/chkconfig ---level 2345 netfs on
The need for remote file-transfer and command-line control sessions is of paramount importance to Unix administrators. For many years, however, only protocols such as FTP, Telnet and RSH were available. These protocols transmitted not only the data of the session but the authentication information as well in cleartext over the network. The advent of the Secure Shell (ssh) protocol introduced a much-welcomed answer to this problem, providing complete encryption of both command-line and data transfer sessions using strong encryption algorithms. Particularly welcome has been the recent development of OpenSSH, a spinoff of the OpenBSD project, which has helped bring this protocol into wider use with its open-source implementation that compiles on any number of different Unix platforms. As a result, most Linux distributions now ship with OpenSSH pre-installed.
While configuration of SSH for command sessions is covered in another section of this text, one feature that is sometimes overlooked is its file-transfer capabilities, intended to replace rcp and ftp at one blow. The scp and sftp commands do an excellent job of replacing their non-encrypted counterparts, emulating the command-line switches and options so well that in most cases, scp in particular can simply be used as a drop-in replacement for rcp . In this section, we'll configure an SSH server such that file transfers using sftp are as secure as possible, including the use of chroot to jail the users' file-transfer sessions, by patching the SSH source code. Unfortunately, the patch currently does not work for scp, but chrooted and non-chrooted users can exist side-by-side.
Red Hat, even with the most current patches, does not always offer the latest SSH build, so it will be necessary to get the portable distribution of OpenSSH from the OpenSSH team (http://www.openssh.com). You can fetch the portable version in a binary RPM, source RPM, or gzipped source tarball; since the chroot will require modifications to the code, we'll need one of the two latter options.
If you're not interested in implementing the chroot feature, you can skip ahead: you'll need the configuration files for SSH featured at the end of this section and you'll be set.
Fetch and unpack the sources
Using Source Tarball | Using Source RPM |
---|---|
cd /usr/src | cd /usr/src |
tar zxvf /usr/src/openssh-3.4p1.tar.gz | rpm -ivh /usr/src/openssh-3.4p1-1.src.rpm |
cd /usr/src/openssh-3.4p1 | cp /usr/src/osshChroot-3.4.diff /usr/src/redhat/SOURCES |
patch -p1 < /usr/src/osshChroot-3.4.diff | cd /usr/src/redhat/SPECS |
add lines to /usr/src/redhat/SPECS/openssh.spec |
Configure, build and install the package
Using Source Tarball | Using Source RPM |
---|---|
./configure \ ---prefix=/usr\ ---with-tcp-wrappers \ ---with-rsh=/bin/rsh \ ---with-default-path=/usr/local/bin:/usr/bin:/bin \ ---with-superuser-path=\ /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ ---with-privsep-path=/var/empty/sshd \ ---with-ipv4-default \ ---with-pam \ ---with-md5-passwords | rpm -bb /usr/src/redhat/SPECS/openssh.spec |
make | cd /usr/src/redhat/RPMS/i386 |
make install | [ If you already have Red Hat's SSH installed ] rpm -Fvh /usr/src/redhat/RPMS/i386/openssh*.rpm [ If this is a fresh install of SSH ] cd /usr/src/redhat/RPMS/i386 rpm -ivh ./openssh-3.4p1-1.i386.rpm rpm -ivh ./openssh-clients-3.4p1-1.i386.rpm rpm -ivh ./openssh-server-3.4p1-1.i386.rpm |
Create the chroot directory
/bin/mkdir /usr/local/chroot cd /usr/local/chroot /bin/mkdir -p bin dev/pts lib/i686 home usr/bin usr/libexec/openssh usr/lib etc var/log for prog in bash cp ls mkdir mv rm rmdir ; do /bin/cp -p /bin/$prog /usr/local/chroot/bin done for file in ld-linux.so.2 libcrypto.so.2 libdl.so.2 libnsl.so.1 libtermcap.so.2 libutil.so.1 ; do /bin/cp -p /lib/$file /usr/local/chroot/lib done /bin/cp -p /lib/i686/libc.so.6 /usr/local/chroot/lib/i686/libc.so.6 /bin/cp -p /usr/lib/libz.so.1 /usr/local/chroot/lib/libz.so.1 cd /usr/local/chroot/dev /bin/mknod null c 1 3 /bin/mknod tty c 5 0 /bin/mknod zero c 1 5 /bin/mknod pts/0 c 136 0 /bin/mknod pts/1 c 136 1 /bin/chmod 650 pts/* /bin/chmod 666 tty null zero /bin/touch /usr/local/chroot/etc/passwd
Test the chroot
To ensure the chroot is working properly, we'll chroot a shell as root. Since sftp uses chroot behind the scenes to perform its actions, we need to make sure that a chrooted shell will have all of the libraries it needs.
[root@host root]# /usr/sbin/chroot /usr/local/chroot /bin/bash bash-2.05a# ls bin dev etc home lib usr var bash-2.05a# exit [root@host root]#
Create the chrooted user account
We will create a single user account to test the chroot: note that the home directory for this user will contain " /./ " as a trigger to the SSH daemon to activate the chroot when this user logs in. This means that users without that trigger can login normally and see the whole filesystem (and will be able to use scp), whereas the chrooted users will use sftp and will be limited to only their own directories.
/usr/sbin/useradd -d /usr/local/chroot/./home/chuser -s /bin/bash -m chuser /bin/grep chuser /etc/passwd >> /usr/local/chroot/etc/passwd /bin/chmod 444 /usr/local/chroot/etc/passwd /usr/bin/chattr +i /usr/local/chroot/etc/passwd
Run the daemon and test the chroot by transferring a file
[root@host root]# /usr/sbin/sshd -D (From another host) [root@other root]# sftp chuser@ssh-host chuser@ssh-host's password: <Enter password> sftp> ls drwx--------- 2 2000 2000 4096 Aug 15 23:07 . drwxr-xr-x 3 0 0 4096 Aug 15 22:59 .. -rw--------- 1 2000 2000 68 Aug 15 22:52 .bash_history -rw-r---r--- 1 2000 2000 24 Aug 15 22:52 .bash_logout -rw-r---r--- 1 2000 2000 191 Aug 15 22:52 .bash_profile -rw-r---r--- 1 2000 2000 124 Aug 15 22:52 .bashrc sftp> pwd Remote working directory: /home/chuser sftp> put foo Uploading foo to /home/chuser/foo sftp> ls drwx--------- 2 2000 2000 4096 Aug 15 23:07 . drwxr-xr-x 3 0 0 4096 Aug 15 22:59 .. -rw-r---r--- 1 2000 2000 17371 Aug 15 23:19 foo sftp> quit [root@other root]# [ START HERE if you're NOT using the chroot patch for sftp ]
Secure the daemon's configuration
On the server, modify /etc/ssh/sshd_config to match the version at the end of this section.
On all clients, modify /etc/ssh/ssh_config to match the version at the end of this section.
Create /etc/issue.net with a suitable warning banner; one is provided in the example section.
Create keypairs
File transfers can be automated (as one might like to do for log rotation and storage or automated backup routines) using RSA or DSA keypairs. To do this, follow these instructions to create your keypairs and transmit them to the server (we'll use a DSA keypair for this example).
On the client:
[user@host user]$ ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/home/user/.ssh/id_dsa): <Press Enter> Enter passphrase (empty for no passphrase): <Enter a passphrase> Enter same passphrase again: <Confirm your passphrase> Your identification has been saved in /home/user/.ssh/id_dsa. Your public key has been saved in /home/user/.ssh/id_dsa.pub. The key fingerprint is: 7b:ab:75:32:9e:b6:6c:4b:29:dc:2a:2b:8c:2f:4e:37 user@host [user@host user]$ ls -l ~/.ssh -rw--------- 1 user user 526 Aug 15 01:21 id_dsa -rw-r---r--- 1 user user 330 Aug 15 01:21 id_dsa.pub [user@host user]$ cd ~/.ssh [user@host user]$ sftp user@sftp-server user@sftp-server's password: <Enter password> sftp> put id_dsa.pub Uploading id_dsa.pub to /home/user sftp> exit
On the server:
[ Login as user on the SFTP server, either through SSH with a password or on the console ] [user@host user]$ mkdir ~/.ssh [user@host user]$ chmod 700 ~/.ssh [user@host user]$ cd ~/.ssh [user@host .ssh]$ mv ../id_dsa.pub ./authorized_keys2 [user@host .ssh]$ chmod 600 authorized_keys2
That should do it! If you entered a passphrase to encrypt the DSA keypair, you'll have to enter it on the client when connecting to the remote host (which is more secure, since the passphrase is never transmitted over the wire). For automated connections, you can create a keypair with a blank password by hitting <CR> when prompted for a passphrase to encrypt the keypair during the generation process. That will mean that anyone with the private half of that keypair ( id_dsa ) can login as that user, so be very careful to guard that file well!
Note | The various "flavors" of SSH (the commercial version from ssh.com, OpenSSH, etc.) differ somewhat in their key formats, especially when exchanging keys between a Windows client and a Unix server. If you need to exchange keys between different flavors of ssh, one option is the ssh-keyinstall utility (http://www.stearns.org/ssh-keyinstall/). |
Add the daemon to the system startup scripts
If you've installed using the source RPM, a quick " chkconfig ”level 2345 sshd on " will activate the SSH daemon; if not, use the SSH startup script in the section covering SSH daemon configuration elsewhere in this guide.
Note | Where files are modified, the unaltered text appears in a normal font, with the needed changes in bold . |
/usr/src/redhat/SPECS/openssh.spec [...] # Do we want to disable building of x11-askpass (1=yes 0=no) %define no_x11_askpass 1 # Do we want to disable building of gnome-askpass (1=yes 0=no) %define no_gnome_askpass 1 [...] # Disable 1Pv6 (avoids DNS hangs on some glibc versions) %define noip6 1 # Do we want kerberos5 support (1=yes 0=no) %define kerberos5 [...] Source1: http://www.pobox.com/jmknoble/software/x11-ssh-askpass/x11-ssh-askpass-%[aversion].tar.gz Patch0: http://chrootssh.sourceforge.net/patches/osshChroot-3.4.diff License: BSD [...] %prep %if ! %{no_x11_askpass} %setup -q -a 1 %else %setup -q %endif %patch -p 1 [...] /etc/ssh/ssh_config Host * # Do not ask for port-forwarding by default ForwardAgent no # Do not ask for X11 forwarding by default ForwardX11 no # Do not ever use .rhosts files for authentication RhostsAuthentication no # Do not use .rhosts file for authentication, even with RSA keypairs RhostsRSAAuthentication no # Use keypairs for authentication, where available RSAAuthentication yes # Fall back to password authentication when necessary PasswordAuthentication yes # By default, ask for passwords interactively BatchMode no # Check that the host's IP matches the key it is presenting in the known_hosts file CheckHostIP yes # Ask the user if she would like to add keys to the known_hosts file when an unknown key is presented StrictHostKeyChecking ask # Use these files for RSA and DSA keypairs by default IdentityFile ~/.ssh/identity IdentityFile ~/.ssh/id_rsa IdentityFile ~/.ssh/id_dsa Port 22 # Use only protocol 2 by default Protocol 2 # Try AES (Rijndael) encryption with a 192-bit key first Cipher aes192-cbc # If that fails, try these ciphers in this order. Ciphers aes192-cbc,aes256-cbc,aes128-cbc,blowfish-cbc,3des-cbc # Use this key to suspend the session to change settings EscapeChar ~ /etc/ssh/sshd_config Port 22 # Use only version 2 of the protocol Protocol 2 ListenAddress 0.0.0.0 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh_ssh_host_dsa_key SyslogFacility AUTH LogLevel INFO # Offer the user 90 seconds to finish authenticating or time out the connection LoginGraceTime 90 # Do not permit root to login directly PermitRootLogin no StrictModes yes RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys RhostsAuthentication no IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no IgnoreUserKnownHosts no PasswordAuthentication yes PermitEmptyPasswords no # Do not use challenge-response-type authentication (unless you're using S/KEY, in which case you'll want to turn this on) ChallengeResponseAuthentication no KerberosAuthentication no KerberosOrLocalPasswd yes KerberosTicketCleanup yes AFSTokenPassing no KerberosTgtPassing no PAMAuthenticationViaKbdInt yes X11Forwarding no X11DisplayOffset 10 X11UseLocalhost yes PrintLastLog yes KeepAlive yes UseLogin no UsePrivilegeSeparation yes Compression yes MaxStartups yes # Print this banner prior to allowing the user to authenticate. # Remember to put a system warning in this file! Banner /etc/issue.net VerifyReverseMapping no Subsystem sftp /usr/libexec/openssh/sftp-server