The /etc/exports file
The /etc/exports file is the NFS server configuration file for Linux systems. It controls which files and directories are exported, which hosts can access them, and what kinds of access are allowed. A sample /etc/exports file might contain these entries:
/usr/man crab(rw) horseshoe(rw) (ro)
/usr/local (ro)
/home/research rodent(rw) crab(rw) horseshoe(rw) jerboas(rw)
This sample file says that:
/usr/man can be mounted by any client, but it can be written to only by crab and horseshoe. Other clients have read-only access.
/usr/local can be mounted by any client, with read-only access.
/home/research can be mounted only by the hosts rodent, crab, horseshoe, and jerboas. These four hosts have read/write access.
The options used in each of the entries in the /etc/exports file determine what kinds of access are allowed. The information derived from the sample file is based on the options specified on each line in the file. The general format of the entries is as follows:
directory [host(option)]...
directory names the directory or file that is available for export. The host is the name of the client granted access to the exported directory, while the option specifies the type of access being granted.
In the sample /etc/exports file shown above, the host value is either the name of a single client or it is blank. When a single hostname is used, access is granted to the individual client. If no host value is specified, the directory is exported to everyone. Like Solaris, Linux also accepts values for domains, networks, and netgroups, although the syntax is slightly different. Valid host values are:
Individual hostnames such as crab or crab.wrotethebook.com.
Domain wildcards such as *wrotethebook.com for every host in the wrotethebook.com domain.
IP address/address mask pairs such as 172.16.12.0/255.255.255.0 for every host with an address that begins with 172.16.12.
Net groups such as @group1.
Notice that in Linux, domain names begin with an asterisk (*), instead of the dot used in Solaris. Also note that the at-sign begins a netgroup name, whereas in Solaris the at-sign is used at the beginning of a network address.
The options used in the sample /etc/exports file are:
ro
Read-only prevents NFS clients from writing to this directory. Attempts by clients to write to a read-only directory fail with the message "Read-only filesystem" or "Permission denied." If ro is specified without a client hostname, all clients are granted read-only access.
rw
Read/write permits clients to read and write to this directory. When specified without hostname, all clients are granted read/write access. If a hostname is specified, only the named host is given read/write permission.
Although specific hosts are granted read/write access to some of these directories, the access granted to individual users of those systems is controlled by standard Unix user, group, and world file permissions based on the user's user ID (UID) and group ID (GID). NFS trusts that a remote host has authenticated its users and assigned them valid UIDs and GIDs. Exporting files grants the client system's users the same access to the files they would have if they directly logged into the server. This assumes, of course, that both the client and the server have assigned exactly the same UIDs and GIDs to the same users, which is not always the case. If both the client and the server assign the same UID to a given user, for example, if Craig is assigned 501 on both systems, then both systems properly identify Craig and grant him appropriate access to his files. On the other hand, if the client assigns Craig a UID of 501 and the server has assigned that UID to Michael, the server will grant Craig access to Michael's files as if Craig owned those files. NFS provides several tools to deal with the problems that arise because of mismatched UIDs and GIDs.
One obvious problem is dealing with the root account. It is very unlikely that you want people with root access to your clients to also have root access to your server. By default, NFS prevents this with the root_squash setting, which maps requests that contain the root UID and GID to the nobody UID and GID. Thus if someone is logged into a client as root, they are only granted world permissions on the server. You can undo this with the no_root_squash setting, but no_root_squash opens a potential security hole.
Map other UIDs and GIDs to nobody with the squash_uids, squash_gids, and all_squash options. all_squash maps every user of a client system to the user nobody. squash_uids and squash_gids map specific UIDs and GIDs. For example:
/pub (ro,all_squash)
/usr/local/pub (squash_uids=0-50,squash_gids=0-50)
The first entry exports the /pub directory with read-only access to every client. It limits every user of those clients to the world permissions granted to nobody, meaning that the only files the users can read are those that have world read permission.
The second entry exports /usr/local/pub to every client with default read/write permission. The squash_uid and squash_gid options in the example show that a range of UIDs and GIDs can be specified in some options.[3] A single UID or GID can be defined with these options, but it is frequently useful to affect a range of values with a single command. In the example we prevent users from accessing the directory with a UID or GID that is 50 or less. These low numbers are usually assigned to non-user accounts. For example, on our Linux system, UID 10 is assigned to uucp. Attempting to write a file as uucp would cause the file to be written with the owner mapped to nobody. Thus the user uucp would be able to write to the /usr/local/pub directory only if that directory had world write permission.
It is also possible to map every user from a client to a specific user ID or group ID. The anonuid and anongid options provide this capability. These options are most useful when the client has only one user and does not assign that user a UID or GID, for example, in the case of a Microsoft Windows PC running NFS. PCs generally have only one user and they don't use UIDs or GIDs. To map the user of a PC to a valid user ID and group ID, enter a line like this in the /etc/exports file:
/home/alana giant(all_squash,anonuid=1001,anongid=1001)
In this example, the hostname of Alana's PC is giant. The entry grants that client read/write access to the directory /home/alana. The all_squash option maps every request from that client to a specific UID, but this time, instead of nobody, it maps to the UID and the GID defined by the anonuid and anongid options. Of course, for this to work correctly, 1001:1001 should be the UID and GID pair assigned to alana in the /etc/passwd file.
A single mapping is sufficient for a PC, but it might not handle all of the mapping needed for a Unix client. Unix clients assign their users UIDs and GIDs. Problems occur if those differ from the UIDs and GIDs assigned to those same users on the NFS server. Use the map_static option to point to a file that maps the UIDs and GIDs for a specific client. For example:
/export/oscon oscon(map_static=/etc/nfs/oscon.map)
This entry says that the /export/oscon directory is exported to the client oscon with read/write permission. The map_static option points to a file on the server named /etc/nfs/oscon.map that maps the UIDs and GIDs used on oscon to those used on the server. The oscon.map file might contain the following entries:
# UID/GID mapping for client oscon
# remote local comment
uid 0-50 - #squash these
gid 0-50 - #squash these
uid 100-200 1000 #map 100-200 to 1000-1100
gid 100-200 1000 #map 100-200 to 1000-1100
uid 501 2001 #map individual user
gid 501 2001 #map individual user
The first two lines map the UIDs and GIDs from 0 to 50 to the user nobody. The next two lines map all of the client UIDs and GIDs in the range of 100 to 200 to corresponding numbers in the range of 1000 to 1100 on the server. In other words, 105 on the client maps to 1005 on the server. This is the most common type of entry. On most systems, existing UIDs and GIDs have been assigned sequentially. Often, several systems have assigned the UIDs and GIDs sequentially from 101 to different users in a completely uncoordinated manner. This entry maps the users on oscon to UIDs and GIDs starting at 1000. Another file might map the 100 to 200 entries of another client to UIDs and GIDs starting at 2000. A third file might map yet another client to 3000. This type of entry allows the server to coordinate UIDs and GIDs where no coordination exists. The last two lines map an individual user's UID and GID. This is less commonly required, but it is possible.