Easy To Use Free Webmaster Resource With Free Webmaster Tools, and Tutorials.

linux security


Navigation - HOME | WEBMASTER TUTORIALS | WEBMASTER TOOLS | PROFESSIONAL SERVICES

Security for linux servers tips




Is your system secure ? (For Dummies) To know if your system is secure you first have to get the list of potential network security holes. Any open Tcp or Udp port, can be used to attack your system, and is a potential security hole. To see which ports are open locally, run 'netstat -a'. Example:

Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        1      0 localhost:12653         localhost:www           CLOSE_WAIT  
tcp        1      0 localhost:12652         localhost:www           CLOSE_WAIT  
tcp        1      0 sone.cf.fr:12642        chaines.voila.fr:www    CLOSE_WAIT  
tcp       81      0 sone.cf.fr:11709        graft.XCF.Berkeley.:ftp CLOSE_WAIT  
tcp        0      0 sone.cf.fr:1023         graft.XCF.Berkeley.o:22 ESTABLISHED 
tcp        0      0 *:6000                  *:*                     LISTEN      
tcp        0      0 *:1024                  *:*                     LISTEN      
tcp        0      0 *:22                    *:*                     LISTEN      
tcp        0      0 *:www                   *:*                     LISTEN      
tcp        0      0 *:printer               *:*                     LISTEN      
tcp        0      0 *:login                 *:*                     LISTEN      
tcp        0      0 *:ftp                   *:*                     LISTEN      
udp        0      0 *:177                   *:*                                 
udp        0      0 *:syslog                *:*                                 
raw        0      0 *:1                     *:*                                 
Active UNIX domain sockets (including servers)
....
....
Above, you can see the list of open connections (Those with 'State=ESTABLISHED'), and Tcp servers listening for incoming connections (State=LISTEN). Some Udp servers are listening too but you won't see the LISTEN state. The 'Local Address' row of LISTENing servers is the most important one, because it gives important informations:
  • on which network interface the server listens (IP address or '*' before : )
  • on which port it listens (number or word after : ), which indicate what kind of service is run

If you run 'netstat -nap' you can even know which programs are listening to these ports (and 'fuser -n tcp [port]' can also be used to identify servers open ports).

On the example we have login,www,ftp,printer,syslog services running and also some others like ssh (port 22), X11 (port 6000). (read also the '/etc/services' file for name<->number translations).

If the network interface is '*', then the concerned service will be likely seen from the external network, so anyone can TRY to connect to that service. This is BAD and you should try to find if the server has an access control list (ACL) feature to secure things (to set some ACL see next chapters).

However, if the network interface is an IP address, that means that the server is listening only for incoming connection on the interface which has that IP address. For example if we only have 'localhost:ftp', then the ftp server is only bound to the localhost interface (e.g. loopback), and won't be seen outside your Ethernet or you Internet PPP connection. THIS Is Great, because you can run services on your system which will never be seen from the outside (internet) !

Note that any other interface name than 'localhost', is bad, because it probably means that the service can be seen outside your computer. So then, carefully check your ACLs !

Now that you have seen which services are running on your system, You probably want to know how it looks when seen from the outside. For that you need to log into a remote system and use Nmap, THE stealth port scanner (get it here). For example, run 'nmap your.ip.address', and you will get the list of all open services seen by anyone on the outside network (Internet maybe).

Now that you have collected information about the services running on your system, it's time to close the holes and shut down the servers/services you don't need.

IP Chains One of the best ways to close the holes (open network ports) is to use the Linux 2.2 firewall mechanism: IP Chains. (man ipchains). 2.4.x kernels series use iptables which will be covered in the next section.

Below you'll find a typical IPChains script to add to your /etc/rc.d/rc.local file, that will:

  • set up the IP Masquerading to protect other hosts on your local network.
  • disable incoming pings and log them.(If someone 'pings' you he won't get any reply but he will be logged.)
  • disable ip spoofing.(and log attempts)
  • block access to the services you do not want for requests coming from any ppp interface (ppp+) to your network (10.0.0.0/24)
  • and (bonus) try to get better delays and throughput.
# Generic IPChains script, accept all by default

# your ipchains executable
$IPC=/sbin/ipchains
# put your local network address below
mynet=10.0.0.0/24
# the interface you want to secure
# here, any PPP interface if you're connected to the internet through a ppp modem link.
iface=ppp+
# reject dns, X11 server, lpd
tcp="53 6000:6010 515"
# reject dns, xdmcp, nfS;
udp="53 177 2049"

# delete previous rules
$IPC -F input
$IPC -F forward
$IPC -F output
# ip masquerading rules (only useful for computers connecting to the internet
# through your system)
$IPC -N user_msq
$IPC -F user_msq
$IPC -A user_msq -s 0/0 -d 0/0 -j MASQ
$IPC -A forward -s $mynet -d 0/0 -i $iface -j user_msq
/sbin/modprobe ip_masq_ftp
# disable ping reply and log incoming pings, so you'll get in /var/log/messages
# IP addresses of little Hackers trying to check if your host is up.
$IPC -A input -l -i $iface -p icmp -s 0/0 echo-request -j DENY 
# improve throughput (0x08) and delays (0x10)
$IPC -A output -p tcp -d 0/0 telnet -t 0x01 0x10               
$IPC -A output -p tcp -d 0/0 ssh -t 0x01 0x10
$IPC -A output -p tcp -d 0/0 ftp -t 0x01 0x10                  
$IPC -A output -p tcp -s 0/0 ftp-data -t 0x01 0x08             
# disable ip spoofing (and log)		     
$IPC -A input -i $iface -s $mynet -l -j DENY
# more blocking
for p in $tcp ; do
    $IPC -A input -p tcp -i $iface -s 0/0 -d 0/0 $p -j REJECT
done
for p in $udp ; do
    $IPC -A input -p udp -i $iface -s 0/0 -d 0/0 $p -j REJECT
done

Of course, you can reject more ports if you want by adding more numbers in tcp and udp lists.

Above, we have set the default policy to ACCEPT IP packets and then REJECT some of them. We could have done the contrary. This may be more secure but could also lead to many programs not working anymore (as you might block more ports than needed). Here is the other way to do it:
# Generic IPChains script, reject all by default

# your ipchains executable
$IPC=/sbin/ipchains
# put your local network address below
mynet=10.0.0.0/24
# the interface you want to secure
# here, any PPP interface if you're connected to the internet through a ppp modem link.
iface=ppp+
# accept only web and ssh
tcp="80 22"
# accept talk ntalk;
udp="517 518"

# the default policy is to reject
$IPC -P input reject
# delete previous rules
$IPC -F input
$IPC -F forward
$IPC -F output
# ip masquerading rules (only useful for computers connecting to the internet
# through your system)
...
... same rules as above
...
# disable ping reply and log incoming pings, so you'll get in /var/log/messages
# IP addresses of little Hackers trying to check if your host is up.
...
# improve throughput (0x08) and delays (0x10)
...
... same rules as above
...
# more blocking (we ACCEPT instead of REJECTing)
for p in $tcp ; do
    $IPC -A input -p tcp -i $iface -s 0/0 -d 0/0 $p -j ACCEPT
done
for p in $udp ; do
    $IPC -A input -p udp -i $iface -s 0/0 -d 0/0 $p -j ACCEPT
done

You should take care of not rejecting 1024 ,1025 tcp or upd ports or you'll get name server problems.

IP Tables This next generation filtering tool is one of the new features included in 2.4.x Linux kernels. Although, you can still use ipchains with 2.4 but you should forget it because, iptables is faster, more flexible, extensible and can much more things for you, such as: source NAT, destination NAT, avoid various denial of service (DoS) attacks, and much more.

But, right now we will only see how to translate our generic ipchains script to an iptables one. Here is the script:
# Generic IPTables script, accept all by default

# path to your iptables executable
IPT=/usr/sbin/iptables
# put your local network address below
mynet=10.0.0.0/24

# the interface you want to secure here
# ppp+ = any PPP interface if you're connected to the internet through a ppp modem link.
iface=ppp+

# our reject lists 
# reject everything but ssh, + squid postgres apache linuxconf
tcp="1:21 23:1023 3128 5432 8080 10000"
# reject everyting + nfs but named
udp="1:52 54:1023 2049"

# delete previous rules
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
$IPT -F POSTROUTING -t nat
$IPT -F PREROUTING -t nat
$IPT -F OUTPUT -t nat

# IP masquerading rules
$IPT -t nat -A POSTROUTING -s 10.0.0.0/24 -o $iface -d 0/0 -j MASQUERADE

# disable ping reply and log incoming pings, so you'll get in /var/log/messages
# IP addresses of little Hackers trying to check if your host is up.
$IPT -A INPUT -i $iface -p icmp -s 0.0.0.0/0 --icmp-type echo-request -j LOG
$IPT -A INPUT -i $iface -p icmp -s 0.0.0.0/0 --icmp-type echo-request -j DROP 

# improve throughput (0x08) and delays (0x10)
$IPT -t mangle -A OUTPUT -p tcp -d 0.0.0.0/0 --dport telnet -j TOS --set-tos 0x10
$IPT -t mangle -A OUTPUT -p tcp -d 0.0.0.0/0 --dport ssh -j TOS --set-tos 0x10
$IPT -t mangle -A OUTPUT -p tcp -d 0.0.0.0/0 --dport ftp -j TOS --set-tos 0x10
$IPT -t mangle -A OUTPUT -p tcp -d 0.0.0.0/0 --dport ftp-data -j TOS --set-tos 0x08

# disable ip spoofing (and log)              
$IPT -A INPUT -i $iface -s $mynet -j LOG
$IPT -A INPUT -i $iface -s $mynet -j DROP

# more blocking
for p in $tcp ; do
  $IPT -A INPUT -p tcp -i $iface -s 0/0 -d 0/0 --dport $p -j REJECT --reject-with tcp-reset  
done
for p in $udp ; do
  $IPT -A INPUT -p udp -i $iface -s 0/0 -d 0/0 --dport $p -j REJECT
done

The new option '--reject-with tcp-reset' allows the firewall to be transparent to port scanners. (If you want to do this with ipchains, you need the 'Return-RST' daemon). As you can see, a basic IPTables script is not very different from an IPChains one. If you go beyond basics, benefits of using iptables over ipchains are great.

TCP Wrappers and Inetd One of the most important things is securing Inetd by configuring TCP Wrappers. Indeed, a stock installation will enable a lot of services (spawned by Inetd) which you will mostly never use. Remember that The more enabled services you have, the most potential security holes you will get.
So edit /etc/inetd.conf and remove every line that is not useful. In particular: echo, discard, daytime, chargen, telnet, gopher, shell, login (and use SSH instead), exec, *talk, pop-*, imap, uucp, *finger, netstat, time, linuxconf. You should leave the 'auth' service, in order to be able to get some informations in the case your system has been used to issue attacks: It enables a server to know which user is behind a socket which helps to finger culprits. (or remove it if you want to become a Cr4CkeR ;-)
Then if you Really NEED some services like ftp, smtp, nntp, imap, pop-3, you should take care that they are run by TCP Wrappers (/usr/sbin/tcpd) and that the latter is properly configured. For example, if ftp is run through TCP Wrappers, you will see a line like
ftp     stream  tcp     nowait  root    /usr/sbin/tcpd  in.ftpd -l -a
To restrict the access to a service, you need to edit /etc/hosts.deny and /etc/hosts.allow files. A good starting point is to add the following line to /etc/hosts.deny to deny every access to Inetd's services:
ALL: ALL
You can also also run a script when an access is denied:
ALL: ALL: (/usr/sbin/safe_finger -l @%h -s %d-%h | mail root) &
That line will try a finger on attacker's host and send the report to root. Or you can try to use the attacker's ident service (rfc931) to log his login as well as his IP:
ALL: ALL: rfc931
Then in /etc/hosts.allow, you can grant access only to your hosts on your local domain with:
ALL: LOCAL 10.0.0. 
You can also add per service policy line:
ftp: 10.0.0.1 
will allow the ftp server only for the host 192.168.1.1 Or even
ftp: linus@10.0.0.1
to match only one user.
For more information about the syntax of these files do 'man hosts_acces'. And use ssh , openssh or other to replace rcp, rlogin, telnet, ftp...

Sendmail Sendmail has been one of the most bugged software and was often used to compromise systems.

The first security rule when using Sendmail is to always upgrade to the latest version (This is also true for other software).

The second one is to tweak the infamous /etc/sendmail.cf file:
- if you use sendmail only to send email without going through your ISP mail gateway, then add 'O DaemonPortOptions=Addr=127.0.0.1'. With this, sendmail will be bound only to the loopback interface, so it won't be seen from the Internet ! (netstat will show '127.0.0.1:smtp' and not '*:smtp'). You can also put your ethernet IP number instead of 127.0.0.1 but, this time you could not send mail locally but other systems on your network could use your sendmail, while hackers on the internet will not see it !
- Add 'O PrivacyOptions=goaway' to disable the VRFY smtp command which can be used to disclose information about the accounts your server.

The third one is to put ip addresses that can use sendmail to relay in the /etc/mail/ip_allow file.

If your sendmail must be seen from anywhere and that you are not afraid of loading your CPU, you can run it from Inetd (with 'sendmail -bs') , so that you can use TCPWrappers ACLs. In that case do not forget to run 'sendmail -q30m' in order to flush the queue periodically.

Finally, here is a little tip about the way to solve a common problem If you use Netscape Communicator for browsing and sending mail: Your email will be used for BOTH ftp login and email. So, anyone on the WEB, can get your email address:
- They simply have to put a fake ftp link in their Web page
- and once you go to the page, Communicator connects to the ftp site (to fetch an image for example)
- and your email is logged by the ftp server and ready to be used by spammers !

To avoid this, use mail address masquerading. You can either set up this in Linuxconf or tweak 'sendmail.cf'. If you add the following lines to 'sendmail.cf':

# Masquerading rules                                                            
S1                                                                              
Rwarez<@mail.net>        $@ me < @ mail.net>                                 
Rwarez<@mail.net.>       $@ me < @ mail.net.>                                
AND then set your email in communicator to 'warez@mail.net', so :
- if you connect to a ftp site, you will send 'warez@mail.net' and your real email won't be disclosed.
- but if you send a mail, sendmail will translate 'warez@mail.net' back to your real email 'me@mail.net'.
So, all in all, you will get much less Spam in your mailbox.

Finally, do not neglect the option to run Sendmail in a chroot prison (, or to run it without the rights of the 'root' user. Most servers (http, ftp,...) usually provide these last two options, to maximize security, and to protect them from some 'not yet discovered bugs'.

Exim Exim, my favorite MTA, and the default MTA chosen by the Debian project has a lot of security related options. For instance, you can restrict which hosts can connect to the mta with the 'host_reject' option:

    host_reject = !1.1.1 : *.com

With the line above you'll reject every host in the .com domain, or not coming from the 1.1.1. network. As Exim is very flexible, if you want to get more dynamic access control you can use LDAP or MySQL queries:


    host_reject = ${lookup ldap {user="cn=manager,o=mysite,c=com" pass=secret 
		    ldap:///o=mysite,c=com?host?(cn=foo)} {$value}fail}
or

    host_reject = ${lookup mysql{select host from acl where id='ph10'}{$value}fail}

In a similar way, with 'host_accept_relay' you can control which hosts can use your MTA as a mail relay to arbitrary domains.

And if you want to bind Exim to a specific network interface, you just have to use the 'local_interfaces' option as shown below:


    local_interfaces = 127.0.0.1 : ::::1               # IPv6 address
We've seen only a tiny part of Exim's features, and now, I hope that you'll throw yourself into Exim's documentation, to discover its power (moreover, for everyone).
Postfix Postfix has an 'inet_interfaces' option similar to sendmail's "DaemonPortOptions=Addr" but what is cool if that you can add multiple interfaces here ! (If anyone has other security tips for Postfix, let me know)
Smail Smail has an 'listen_name' option similar to sendmail's "DaemonPortOptions=Addr".

Also, with the 'smtp_remote_allow' option you can set up simple host based access control.

DNS, Bind If one looks back over past events, like Sendmail, Bind has an eventful past. So, always upgrade to the latest version.

Fortunately, you can easily add ACLs in '/etc/named.conf'. In the example below you can see the setup of an ACL named 'internal' which contains the specification of our local network. You can add as many 'acl' sections as you want. Then in the 'allow-query' sub-section of 'options', you can add your global ACLs . The 'allow-query' option can also be local to a zone of you DNS.


    acl internal {                                                               
            10.0.0.0/24;                                                        
            127.0.0.0/24;                                                       
    };                                                                          
    options {                                                                   
           allow-query {                                                        
                   internal;                                                       
         };                                                                    
     };                                                                          
In the same way you should restrict zone transfers with the 'allow-transfer' directive in a zone definition, as your network topology can be a valuable information to a hacker which wants to break in.

As most other servers, you can also run Bind in a chroot prison (-t command line option), and/or an other user than the default 'root' (-u command line option), in order to minimize damages in case of a 'break-in'.

Samba ACLs are here set by the 'hosts allow' parameter. It can be set either in the '[global]' section of 'smb.conf', or in any share section. As you can see below, the syntax is trivial:
              
    hosts allow = 10.0.0., 127. , myhost.mydomain 
or

    hosts allow = 10.0.0. EXCEPT 10.0.0.200
and even,

    hosts allow = 10.0.0.0/255.255.255.0
You can also play with the 'host deny' parameter which has the inverse effect. Of course, Samba provides support for binding the servers on only one interface with the 'bind interface only' parameter which can be set in the global section.

For example, the following configuration will make smbd and nmbd listen only on one interface.

    bind interfaces only = True
    interfaces = 192.168.0.0/255.255.255.0
Apache Access control in Apache is very powerful and flexible.

Below, you can see how to protect a single page (add this to the global 'httpd.conf' file). Of course, you can protect entire directories by replacing '<Files' by '<Directory'. Note that the authorization realm (words after AuthName) should be unique. To create the password file (/home/bill/apache.htpasswd in this example), use the 'htpasswd' utility.

        <Directory /home/bill/public_html>
	        <Files thesecret.file>
		        AuthName "Bill secret stuff"
			AuthType Basic
			AuthUserFile /home/bill/apache.htpasswd
			Require valid-user
		</Files>
	</Directory>
Below, is a more interesting configuration example.
It shows how to get unrestricted access to a file when it is viewed from the local network (10.0.0.0/255.0.0.0), but for external accesses, a password is required:
    <Files foo.html>
            Order Deny,Allow
               Deny from All
               Allow from 10.0.0.0/255.0.0.0 
            AuthName "Insiders Only"
            AuthType Basic
            AuthUserFile /home/httpd/etc/htpasswd
            Require valid-user
            Satisfy Any
    </Files>
Instead of an entire network (10.0.0.0/255.0.0.0), you can also deny a single host by setting 'Allow from 10.2.3.4' or 'Allow from foo.com', although the later form is slower because of the required reverse DNS lookup.

In fact, Apache security features and logging options are so powerful, that a complete description is beyond the scope of that page. Refer to the Apache manual for more information.

RPC and NFS Latest version of RPC (which is used by NFS) rely on the same files used by Inetd for access control. So, in order to make your NFS a little more secure, you can add this to '/etc/hosts.allow'
      
    portmap: 127.0.0.1 10.0.0.2 10.0.0.1 255.255.255.255 0.0.0.0                
And this, to '/etc/hosts.deny':
                                                   
    portmap: ALL: (/usr/sbin/safe_finger -l @%h | mail root) &                  

Another problem: Programs using RPCs, often randomly choose their server port, then properly configuring your firewall can be tricky. For example 'NFS' is most of the time bound to port 2049 but 'mountd' will choose an unsed port after 1024. Fortunately, you can force 'mountd' port: add a '-P 909' option on rpc.mount launch script. Filtering mountd's UDP port is now trivial !
Lpd The standard line printer daemon allows you to set up basic ACLs by adding authorized hosts to the '/etc/hosts.lpd' file. I still do not know if Lprng, the new generation line printer daemon, has more network security options. Anyway, it should be more robust. If you can, remove lpd and switch to lprng.

 

 

 

Search Query

 

contact us | webmaster forum | web hosting support | webmaster links | general links

 

 

 

 

© Copyright 2002-2005. All rights reserved.
Easy Website Promotion
| DWHS Web Hosting | Verocom Communications