[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
authenticated NFS
-----BEGIN PGP SIGNED MESSAGE-----
If you're not interested in doing authenticated NFS,
read no more. I am using it right now, and i thought others might want
to know how.
First off, you'll need to compile your kernel(s) with the IPSEC and
IPFILTER options.
Setup the NFS server and client(s) as usual. This is the
server-specific setup part:
/etc/netstart (at the end)
- --------------
/sbin/ipsecadm hmacsha1 0.0.0.0 <server IP address> <SPI0> <key0>
/sbin/ipsecadm hmacsha1 <server IP address> <client1 address> <SPI1> <key1>
/sbin/rt 0.0.0.0 255.255.255.255 <client1 address> 255.255.255.255 17 \
2049 0 <client1 address> <SPI1> 0
/sbin/rt <server IP address> 255.255.255.255 <client1 address> \
255.255.255.255 17 2049 0 <client1 address> <SPI1> 0
Now, what do these mean ? The "hmacsha1" means use the
IPSEC-AH-HMAC-SHA1 transform, which uses SHA1 for keyed authentication
and does replay protection. An alternative would be "hmacmd5". You
should pick <SPI?> (doesn't matter what value it is). <key?> is the
key used for the authentication, and should be at least 40 hex
characters (20 bytes), but it can be arbitrarily large. <client?
address> is the address of the NFS client. For every client you have,
you copy the last 3 lines, and change the <client? address>, <SPI?>
and <key?> arguments accordingly. What the last two lines mean is:
"packets from me to <client1> using protocol UDP (17), from port 2049
(NFS server) to any port of his, use the security association defined
by <client1>/<SPI1>/<0>, where 0 means we're doing authentication"
If you're doing NFS over TCP, change the "17" to "6" of course.
You might also want to copy the last two lines and change "2049" to
"111" (portmapper).
As an example (server is 158.130.6.141, client is158.130.6.77):
/sbin/ipsecadm hmacsha1 0.0.0.0 158.130.6.141 101 \
a8714376125376125376512312bb53123e12765f
/sbin/ipsecadm hmacsha1 158.130.6.141 158.130.6.77 abcd \
9874981703492845a876ad8768768768123cceff234d
/sbin/rt 0.0.0.0 255.255.255.255 158.130.6.77 255.255.255.255 17 2049 \
0 158.130.6.77 abcd 0
/sbin/rt 158.130.6.141 255.255.255.255 158.130.6.77 255.255.255.255 17 2049 \
0 158.130.6.77 abcd 0
/sbin/rt 0.0.0.0 255.255.255.255 158.130.6.77 255.255.255.255 17 111 \
0 158.130.6.77 abcd 0
/sbin/rt 158.130.6.141 255.255.255.255 158.130.6.77 255.255.255.255 17 111 \
0 158.130.6.77 abcd 0
Similarly, for the client:
/sbin/ipsecadm hmacsha1 0.0.0.0 158.130.6.77 abcd \
9874981703492845a876ad8768768768123cceff234d
/sbin/ipsecadm hmacsha1 158.130.6.77 158.130.6.141 101 \
a8714376125376125376512312bb53123e12765f
/sbin/rt 0.0.0.0 255.255.255.255 158.130.6.141 255.255.255.255 17 0 \
2049 158.130.6.141 101 0
/sbin/rt 158.130.6.77 255.255.255.255 158.130.6.141 255.255.255.255 \
17 0 2049 158.130.6.141 101 0
/sbin/rt 0.0.0.0 255.255.255.255 158.130.6.141 255.255.255.255 17 0 \
111 158.130.6.141 101 0
/sbin/rt 158.130.6.77 255.255.255.255 158.130.6.141 255.255.255.255 \
17 0 111 158.130.6.141 101 0
Now, these insure that packets from the server's NFS and portmapper
to that client will be authenticated, and vice versa.
There's one last step involved however: how to stop non-authenticated
packets (possible from some other, malicious host) from reaching the
server (or the client). For that, you'll need IPFILTER. To continue
with the example, at the server's /etc/ipf.rules you'll need to add:
# Remember, you need to set ipfilter to YES at /etc/netstart for
# these to take effect...read the man pages (start with man ipf)
# Block unauthenticated portmapper calls from 158.130.6.77
# I personally allow only authenticated calls to my portmapper, so
# i've substituted "158.130.6.77" with "any"
# Substitute "de0" with your ethernet interface
block in quick on de0 proto tcp/udp from 158.130.6.77 to any port = 111
# Block unauthenticated NFS requests
# I also allow only authenticated NFS, so i've substituted
# "158.130.6.77" with "any"
block in quick on de0 proto tcp/udp from 158.130.6.77 to any port = 2049
Similarly, at the client:
# Block unauthenticated NFS replies
block in quick on de0 proto tcp/udp from 158.130.6.141 port = 2049 to any
# Block unauthenticate portmap replies
block in quick on de0 proto tcp/udp from 158.130.6.141 port = 111 to any
Now, the reason these blocks work is that incoming packets originally
have their protocol number set to 51 (IPPROTO_AH), and when they
have successfully been verified, their incoming interfaces is changed
to "enc0". The above example was for those who have the rule "allow
unless explicitly blocked". For those who "block unless explicitly
permitted", you can use this:
# Server side
pass in quick on enc0 proto tcp/udp from 158.130.6.77 to any port = 2049
pass in quick on enc0 proto tcp/udp from 158.130.6.77 to any port = 111
# Client side
pass in quick on enc0 proto tcp/udp from 158.130.6.141 port = 2049 to any
pass in quick on enc0 proto tcp/udp from 158.130.6.141 port = 111 to any
Encrypted NFS is also possible, but i won't go into it now (it's very
similar to authenticated NFS). And of course, these two can be
combined.
I'm doing this between a P166 and a SPARC LX; i export /usr/src to the
SPARC, to avoid having two source trees. I'm currently compiling a new
kernel over NFS, and i haven't noticed considerable degradation of
performance.
Finally, all these will become much easier (and mostly unnecessary)
once Niels Provos commits the Photuris key management daemon source in
the CVS tree. This message was mostly intended as a heads-up for the
wonderful things to come.
- -Angelos
PS. No, the keys on the examples are not the ones i'm using :-)
-----BEGIN PGP SIGNATURE-----
Version: 2.6.3i
Charset: noconv
Comment: Processed by Mailcrypt 3.4, an Emacs/PGP interface
iQCVAwUBM8mDK70pBjh2h1kFAQHVKQP9Hjy0MA81GxMMeipggHUafJpZZOkvvKnC
UBcELLg/sklo7g13qy5CJJKNxb6r6QNpKUKFStO5mzcaHKugff/KCkKUf+pT7v+1
7TeqKsu+SF0t8pVlCkf1UmRhnDXxcdcK18DcDYMVI6ZCNbWwiEp+ZRL2QddWDUFe
3SlK0ru4D9g=
=lukk
-----END PGP SIGNATURE-----