My project du jour is getting updating the firewall for the lab from RedHat 8 to Fedora Core 3. We are doing a Linux install for the lab so we can have a training toward the end of the month.
The firewall will actually be serving several important functions for the lab:
Actually installing the system was something of a challenge.
I've got the ISO images, but no blank CDs. I used a funky HTTP install for the
machines in the lab, but the firewall only has 32mb of RAM and the
FC3 installer refuses to run. So, I had to actually pull the drive
and run the install in another box and then move it back.
Disappointingly, the support for the ISA network cards which were
auto-detected in RedHat 8, did not work in FC3. I had to go in and
edit /etc/modprobe.conf
by hand.
After some mucking about thought I managed to get it up and running. It was not horrible, but the number of problems I had definitely would have thwarted almost any novice:
Finally though it was up and running with all the hardware working.
My little lab is NATed away from the rest of the university. We didn't used to be this way, but students here are frequently changing the IP addresses as a part of the course and though I emphasized the importance of being careful, they weren't. The university admins got frustrated with it and eventually stuck us off on our own. I prefer this solution to the previous one, which was simply to unplug our lab from the main switch.
The NAT was quick and simple: (we are
192.169.99.0/24
and the uni is
192.168.2.0/24
)
iptables -t nat -A POSTROUTING -s 192.168.99.0/255.255.255.0 -j SNAT --to-source 192.168.2.176 service iptables save
There is also a server for the Cisco curriculum and a SMB fileserver at
192.168.99.250
. I wanted that traffic to pass
through, so I also did:
iptables -t nat -A PREROUTING -d 192.168.2.176 -p tcp -j DNAT \ --dport 80 --to-destination 192.168.99.250 iptables -t nat -A PREROUTING -d 192.168.2.176 -p tcp -j DNAT \ --dport 138:139 --to-destination 192.168.99.250 iptables -t nat -A PREROUTING -d 192.168.2.176 -p udp -j DNAT \ --dport 138:139 --to-destination 192.168.99.250 service iptables save
The DNS servers provided Mauritel are fairly unreliable. For this reason and to provide dynamic DNS in conjunction with the DHCP, I wanted to run a DNS server.
The setup is simple enough. I added a couple zones (forward and reverse) to the
chroot jail
at /var/named/chroot/var/named/
for the local
addresses in the lab and then added the shared dyndns stuff to
/etc/named.conf
.
This was the first place I hit a snag. Something new in FC3 was the integration of Security Enhanched Linux (SELinux). I've never used it before and it was denying access to the new zones that I'd created.
The problem with traditional Linux security is granularity. There are normal users and there is root and the layering of protections between them is pretty slim. For instance, to run a program like Apache, I have to be able to bind port 80. To do so, the process has to be running as root. Another term for root is the "superuser" and while running as root I embody that term in a Nietzscheian übermensch kind of way. I can look at or delete anyone's files I want to. I can send out forged emails or sniff network traffic. I am above the law and only bounded by my capabilities and imagination.
The process that is normally used is to mediate this problem is that the Apache process will essentally give up its Godhood and become a normal user after it has done whatever it needed to do. This process though has its problems, mostly inherent in having to trust Apache. A better solution would be to be able change the environment so that Apache was only given limited power in the first place so even if it is made to misbehave, it can't do any harm. This is what SELinux begins to provide.
All subjects (users, programs or processes) and objects (files and devices) are now assigned identities, roles and types. There are security policies which are made based on those attributes.
The error I am getting when I try and start named is:
audit(911588074.103:0): avc: denied { read } for pid=15535 exe=/usr/sbin/named name=named.conf dev=dm-0 ino=267969 scontext=root:system_r:named_t tcontext=root:object_r:user_home_t tclass=file
If I just look at the file permissions, everything seems fine:
ls -l named.conf* -rw-r--r-- 1 root named 1547 déc 12 2004 named.conf -rw-r--r-- 1 root root 1329 nov 20 02:10 named.conf.orig
The file is readable by the named
user who is what
the bind process is running as. When we look at the SELinux
contexts though, we can see the problem. (The programs
ls
, ps
and id
all now take
a Z
parameter than shows SELinux contexts.)
ls -lZ named.conf* -rw-r--r-- root named root:object_r:user_home_t named.conf -rw-r--r-- root root root:object_r:named_conf_t named.conf.orig
The file
/etc/selinux/targeted/src/policy/domains/program/named.te
contains the directive: (I had to install the
selinux-policy-targeted-sources
package to have the
source.)
r_dir_file(named_t, named_conf_t)
This means that subjects of type named_t
should be
given read access to objects of type named_conf_t
.
Previously in the file there was the line:
can_exec(named_t, named_exec_t)
Which means that subjects of type named_t
can
execute objects of type named_exec_t
.
(/usr/sbin/named
is of type
named_exec_t
.)
So, to fix my problem, I have to fix the context. The way to that is:
restorecon -v /var/named/chroot/etc/named.conf
The same problem exists for the new zone files, so I also have to do:
restorecon -v /var/named/chroot/var/named/*
In an attempt to reduce the number of problems that we are having with misconfigured machines, I set up a DHCP server. The setup is pretty straight forward. I got the mac address off of each machine set up some blocks:
192.168.99.0/26
(192.168.99.0
- 192.168.99.63
)192.168.99.64/26
(192.168.99.64
- 192.168.99.127
)192.168.99.192/26
(192.168.99.192
- 192.168.99.254
)
192.168.99.254
192.168.99.250
192.168.99.251
The basic file came from
/usr/share/doc/dhcp-3.0.1/dhcpd.conf.sample
and I
edited it and put it at /etc/dhcpd.conf
.
There is a SELinux problem here as well. There is a ownership
problem like with named, but additionally, for the dnydns there is
a shared file, /etc/rndc.key
, with the authentication
key used to update the server.
When I initially tried to run the program, I got an access denied error and in the logs it said:
audit(911596073.741:0): avc: denied { search } for pid=16624 exe=/usr/sbin/dhcpd name=named dev=dm-0 ino=426311 scontext=root:system_r:dhcpd_t tcontext=system_u:object_r:named_zone_t tclass=dir
/etc/rndc.key
is just a symlink to
/var/named/chroot/etc/rndc.key
. The directory is of
type named_conf_t
which by the default policy dhcpd
can't access. There is probably a more graceful way to deal with
this problem, but all I did was to grant it premission to the
whole context: (as well as giving permission to read
rndc.key
of the same type)
cat >> /etc/selinux/targeted/src/policy/domains/program/dhcpd.te << EOF # Added to allow shared key config with bind: allow dhcpd_t named_conf_t:dir { search }; allow dhcpd_t named_zone_t:dir { search }; allow dhcpd_t named_conf_t:file { read getattr }; EOF make -C /etc/selinux/targeted/src/policy/ load
I've done the DNS and DHCP servers before. I've even done a domain controller and some LDAP programming. I've never had a Linux lab to run before, so this was my first time setting up a shared authentication source for Linux boxen. The majority of the information on the setup came from the Linux Documention Project.
The first issue was to get the server up and running. This took
an edit of /etc/openldap/slapd.conf
to set
the suffix
, rootdn
and
rootpw
. Also I tighetened the default security policy
which is nonexistent and enabled TLS.
The default security policy gives everyone read access to
everything, which is something of a problem. It also restricts
write access only to the server administrator which means no users
can change their passwords. So the security changes in slapd.conf
have to
be put into place before the setup will work.
Also, the migration will put the entries into an organizational
unit, People
under the base dn and groups under
Group
. Once the server is started you have to create
those base entries. If
necessary, you can clear the directory first using
ldapdelete
or just removing all the data files in
/var/lib/ldap/
.
service ldap stop rm -rfv /var/lib/ldap/* service ldap start admin=$(grep -e ^rootdn /etc/openldap/slapd.conf | \ sed -e "s/^rootdn[[:space:]]\+\"\([^\"]\+\)\"/\\1/") ldapadd -H ldaps://localhost -D "$admin" -xW -f base.ldif
To migrate the existing information over to LDAP uses some perl scripts incuded in the
distribution. Some setup is required by setting the environment
variable LDAP_BASEDN
before running:
export LDAP_BASEDN="o=Académie Cisco,o=Université de Nouakchott,c=MR" /usr/share/openldap/migration/migrate_passwd.pl /etc/passwd > passwd.ldif ldapadd -H ldap://localhost -D "$admin" -xW -f passwd.ldif /usr/share/openldap/migration/migrate_group.pl /etc/group > group.ldif ldapadd -H ldap://localhost -D "$admin" -xW -f group.ldif
This firewall will not actually be authenticating against the
LDAP server, so the other changes are to the clients. I needed to
update the configuration of the name service switch at
/etc/nsswitch.conf
,
the PAM config at /etc/pam.d/system-auth
and
the default LDAP config at /etc/ldap.conf
.
(system-auth
and
ldap.conf
were primarily updated by authconfig
.) Also, to unify
things a bit, I removed /etc/openldap/ldap.conf
and
made that a symlink to /etc/ldap.conf
. Nsswitch
uses the file in etc
and ldapsearch
uses
the one in openldap
, but the format is the same.
The one important thing to note with using the same file for
both /etc/ldap.conf
and
/etc/openldap/ldap.conf
is that
PAM does not respect the uri
directive, and so if you
used that it is also necessary to include a host
entry.
The debugging of this step proved a little troublesome, some commands that I found useful:
To verify that the ldap server was running and that I could connect from the client:
ldapsearch -x -H ldaps://firewall "(uid=will)"
On the server, in order to know which connections were being made and how, I did:
slapd -u ldap -d 1 -h "ldap:/// ldaps:///"
The debug levels is a bitmask (so you add the values to combine them):
Level | Effect |
---|---|
-1 | enable all debugging |
0 | no debugging |
1 | trace function calls |
2 | debug packet handling |
4 | heavy trace debugging |
8 | connection management |
16 | print out packets sent and received |
32 | search filter processing |
64 | configuration file processing |
128 | access control list processing |
256 | stats log connections/operations/results |
512 | stats log entries sent |
1024 | print communication with shell backends |
2048 | print entry parsing debugging |
In the end I turned on all debugging and found that my problem
was I had used both a ldaps://
uri and the ssl
start_tls
command in /etc/ldap.conf
. It was
trying to start TLS twice and was failing. After this was fixed I
could do:
getent passwd
And it would return results both from /etc/passwd
on the machine and from the LDAP server.
Also the passwd
command now works correctly to
change passwords. The one potential issue is I can't change a
user's password without knowing their old password. The system has
to bind the LDAP server with an account with the permission to
change the password and only the user and rootdn
have
that right. What I would like is to have it use the
rootdn
to bind when I'm running as root. I can have
it do that, but only if I store the password in
/etc/ldap.secret
and I don't want to do that on all
the workstations. I'll have to deal with this later.
Though my lab is a salle of logiciel libre, the primary operating system currently installed is XP Pro with French and Arabic MUI. A nice setup even if it does come from the evil empire. Hopefully with this new Fedora setup I can get some people weaned.
The machines all have really restricted local user accounts that only let the students read and run a few basic programs. For the other teachers and myself though I want for them to be able to log in with a roaming profiles. Given that I hardly want to have to touch each computer to add accounts, I need a domain controller.
It just took making a few changes to the default
/etc/samba/smb.conf
.
Before I could use the tools included for managing the LDAP server, I had to install a perl LDAP module:
perl -MCPAN -e 'install ldap'
Or, actually for the server I was setting up I was having a problem with the OOM killer kicking in and killing off both the CPAN update and my ssh session, so I had to do the install by hand:
After the modules were installed, I updated the config file for the included ldap tools at /usr/share/doc/samba-3.0.8/LDAP/smbldap-tools/smbldap_conf.pm. Then I ran the script to create all the needed base entries:
perl /usr/share/doc/samba-3.0.8/LDAP/smbldap-tools/smbldap-populate.pl
Then I added a couple NT accounts just to try out that it was working:
smbpasswd -a root
To see if I could connect then I did:
smbclient //localhost/root -U root
Now I wanted to take hosts and join them to the domain controller. Each machine has to be added to the database to join the domain. To do this automatically, the domain controller needs access to some scripts. Rather than putting the actual paths in the config file, I made some symbolic links:
groupadd smbdomain mkdir -p /home/samba/netlogon