Sysadmins are far too busy (lazy) to monitor logs properly; intruders unhelpfully edit logs to hide their presence. Both issues can be addressed by setting up a log server: such a machine collects system logs from many client machines via UDP remote-logging.
For both forensic and legal reasons, date/timestamps of log messages must be accurate. To achieve this, all log clients and the log-server should use NTP (or an equivalent service) to keep system clocks set accurately.
Syslog can be used to collect logs from client machines, but is ill-suited to the task — it's showing its age: it is not obvious, for example, how to separate logs from different machines into different directories; with dozens or even hundreds of clients this is a must. Syslog NG is a prime candidate to use instead.
Syslog-NG can be installed from source via the classic .configure, make, make install sequence; Debian packages are available.
Options which affect the security of the server include:
-u <username> } after initialisation drop root privileges and run -g <group> } as <username>:<group> -C /chroot/path after reading the config file, chroot to path givenHaving Syslog-NG listening as root is a very bad idea, so set up a suitable username and group, for example:
/etc/group syslogng:x:77: /etc/passwd syslogng:x:99:65534::/var/chroot/syslogng:/bin/false
The configuration file /etc/syslog-ng/syslog-ng.conf is divided into options, sources, destinations, filters and logs.
options affecting server security include:
options { # -- resolve address of message sender? show names of all hosts by # which the message has been handled? use_dns(no); chain_hostnames(no); ##dns_cache(yes); # ...syslog-ng blocks on DNS queries, so enabling DNS may lead # to a DOS, hence set both of the above to "no"... # -- enable or disable directory creation for destination files create_dirs(yes); # ...macros in the config file (see below) mean that new dirs # will be created as packets from new IP addresses are # encountered --- this could be an issue if packets are spoofed, # but appropriate firewalling should resolve this issue... # default owner, group, and permissions for log files # (defaults are 0, 0, 0600) owner(syslogng); group(adm); perm(0640); # default owner, group, and permissions for created directories # (defaults are 0, 0, 0700) dir_owner(syslogng); dir_group(syslogng); dir_perm(0755); };
Here are couple of likely sources for a central log-server. First, we'll want to log our own messages plus standard stuff from our own host OS:
source s_local { # -- messages generated by Syslog-NG : internal(); # -- standard Linux log source (location to which syslog() function # sends messages by default) : unix-stream("/dev/log"); # -- messages from the kernel : file("/proc/kmsg" log_prefix("kernel: ")); };Secondly, we want to listen for incoming UDP-based messages from our clients:
source s_udp { # -- receive remote UDP logging messages (equivalent to the "-r" # syslogd flag) udp(ip(0.0.0.0) port(514)); };
Here is a particularly simple treatment of our own local messages:
destination df_auth { file("/var/log/auth.log"); }; destination df_syslog { file("/var/log/syslog"); }; filter f_auth { facility(auth, authpriv); }; filter f_syslog { not facility(auth, authpriv); }; # -- auth,authpriv.* /var/log/auth.log log { source(s_local); filter(f_auth); destination(df_auth); }; # -- *.*;auth,authpriv.none -/var/log/syslog log { source(s_local); filter(f_syslog); destination(df_syslog); };
Local boot-related messages:
# -- local7.* /var/log/boot.log destination df_boot { file("/var/log/boot.log"); }; filter f_boot { facility(local7); }; log { source(s_local); filter(f_boot); destination(df_boot); };
We can use Syslog-NG macros to help us in dealing with messages from our clients. We don't want them all jumbled together. This way each client gets its own directory:
destination hosts { file("/var/log_hosts_by_facility/$HOST/$FACILITY.log" owner(root) group(root) perm(0600) dir_perm(0700) create_dirs(yes)); }; log { source(s_udp); destination(hosts); };
To help prevent a DOS attack on the server, suitable firewalling is essential. Here is the most basic:
$IPTABLES -t filter -A INPUT -p udp -s server.umist.ac.uk --dport 514 -j ACCEPT $IPTABLES -t filter -A INPUT -p udp -s host.umist.ac.uk --dport 514 -j ACCEPT $IPTABLES -t filter -P INPUT DROP
Ideally all services on a server which listen on a publicly accessible port chroot should be chrooted for security reasons. Syslog-NG is no exception.
Syslog-NG has a built-in option to chroot itself after binding to port 514. This means that the chroot environment to be built can be greatly simplified (which means less for a potential intruder to play with if they can get into the jail, and less for us to maintain): we do not need a shell and its supporting libraries, or many of the files syslog-ng opens on startup, before it chroots (use lsof to see that there are quite a few of these).
Mick Bauer has written a HOW-TO. The words below are based on that: this version is simplified — since all DNS look-ups are turned off in our configuration (to eliminate a possible DOS attack), none of /etc/resolv.conf, /etc/nsswitch.conf and libnss*.so.* are required.
$LOGJAIL/etc/syslog-ng $LOGJAIL/dev/ $LOGJAIL/var/logwhere e.g. $LOGJAIL=/var/chroot/syslog-ng.
syslogng:x:99:65534::/var/chroot/syslogng:/bin/false syslogng:x:77:to $LOGJAIL/etc/passwd and $LOGJAIL/etc/group, respectively — these can be the only entries in these files.
cd /etc/syslog-ng mv syslog-ng.conf $LOGJAIL/etc/syslog-ng ln -s $LOGJAIL/etc/syslog-ng/syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
cd $LOGJAIL/dev mknod -m 0660 xconsole p mknod -m 0660 tty10 c 4 10 chgrp syslogng ./xconsole ./tty10(xconsole is a pipe and is used as a destination — see syslog-ng.conf; tty10 is a character device with major and minor numbers 4 and 10, respectively: it seems traditional to send syslog output to tty10 — you can watch it using CTRL-ALT-F10 locally, or using ttysnoop.)
The following simple init script is all that's necessary to start syslog-ng and have it chroot itself:
/etc/init.d/syslog-ng #! /bin/sh case "$1" in start) /sbin/syslog-ng -C /var/chroot/syslogng -u syslogng -g syslogng || ex\ it 1 ;; *) echo "Usage: /etc/init.d/syslog-ng start" >&2 exit 1 ;; esac exit 0
pkill syslog-ng
The usual way to restart syslog-ng after a configuration change (or after a log rotation) is to kill -HUP the process. This will not work in the above jail as the already-chrooted process will not be able to bind to port 514 (a privileged port, as there is not root user in the jail), not are many required files available, e.g., /dev/kmesg and a bunch of shared-object libraries (use lsof to see which).
Assuming this actually presented a problem, one could build a more complex jail in which one could "manually" start syslog-ng (and in which it would therefore be restartable), like this:
chroot /var/chroot/syslog-ng bash /sbin/syslog-ng -u syslogng -g syslogng # ...that's /var/chroot/syslog-ng/sbin/syslog-ng now...
Since syslog-ng cannot be restarted within its jail (see above), we have to use the copytruncate option when using logrotate, for example:
/var/chroot/syslogng/var/log_hosts_by_facility/130.88.*/*.log { rotate 28 daily copytruncate missingok notifempty compress }
...previous | up (conts) | next... |