This is an old revision of the document!


Linux Setup

Installation

  1. Download CD images (ISO files) from http://fedora.redhat.com
  2. Burn the ISO images into CDROMs.
  3. Install Fedora.
  4. Partition hard disk as necessary.
  5. Install all the required software packages.

Adding a New Hard Drive

  1. Create partition using fdisk /dev/<partitionname>. Eg:
    % fdisk /dev/hdb1
  2. Format new partition using mkfs -t ext3 /dev/<partitionname>. Eg:
    % mkfs -t ext3 /dev/hdb1
  3. Check new partition file system integrity using fsck -f -y /dev/<partitionname>. Eg:
    % fsck -f -y /dev/hdb1
  4. Mount the new partition. First create a folder where to mount (Eg: /data), then mount. Eg:
    % mkdir /data
    % mount /dev/hdb1 /data
  5. Add entry to file /etc/fstab for automatic mounting. Eg:
    /dev/hdb1   /data ext3  defaults   1 1
Linux Configuration

Global Aliases

Setup some basic aliases for users to have a simpler navigation at the command line. Add the following commands to /etc/profile.d/sysaliases.sh:

alias l='ls -l'   # display file list in long format
alias ll='ls -la' # display file list in long format and include all files (hidden as well)
alias cls=clear   # clear the screen

Alternatively, you can add these commands at the end of file /etc/bashrc.

User Information

  • Use chfn to change user finger information (full name, office, phone, etc).
  • Use chsn to change user login shell.
  • Use finger username to view the current finger information. For example:
  $ finger jdoe
  Login: jdoe                             Name: John Doe
  Directory: /home/jdoe                   Shell: /bin/bash
  Office: Software Development, 211
  On since Mon Aug 14 09:29 (EDT) on pts/0 from 192.168.0.3
  No mail.
  No Plan.

Apache

''htaccess'' Authentication

Create .htaccess file

  • NOTE 1: < protectedfolder > is where the actual folder name is going to be
  • NOTE 2: The password file path in AuthUserFile should ideally be outside of the webserver root.
AuthType Basic
AuthName "Only for Authenticated Users. Please contact your sales representative for a username and password"
AuthUserFile /data/www/html/<protectedfolder>/.htpasswd
<Limit GET>
        Require valid-user
</Limit>

Create a password file and add a user:

% cd /data/www/html/<protectedfolder>
% htpasswd -c .htpasswd <username>

Only add a username and password (no creation of password file):

% cd /data/www/html/<protectedfolder>
% htpasswd .htpasswd <username>

Troubleshooting ''htaccess''

Source: Apache Tutorial: htaccess Files 1)

When you put configuration directives in a .htaccess file, and you don't get the desired effect, there are a number of things that may be going wrong.

Most commonly, the problem is that AllowOverride is not set such that your configuration directives are being honored. Make sure that you don't have a AllowOverride None in effect for the file scope in question. A good test for this is to put garbage in your .htaccess file and reload. If a server error is not generated, then you almost certainly have AllowOverride None in effect.

If, on the other hand, you are getting server errors when trying to access documents, check your Apache error log. It will likely tell you that the directive used in your .htaccess file is not permitted. Alternately, it may tell you that you had a syntax error, which you will then need to fix.

Look for this statement (and comment it out) in file /etc/httpd/conf/httpd.conf (or /etc/apache2/sites-available/default in Ubuntu). It should be:

  #AllowOverride None 

Default Character Encoding

Some pages will display characters incorrectly. The character encoding might need to be changed from the default UTF-8 to the following (file /etc/httpd/conf/httpd.conf):

AddDefaultCharset ISO-8859-1

PHP Input Filters

For installations with PHP 5.1 or higher, this step is not necessary since the filters are installed by default. For other installations, setup PHP filters using the following commands:

$ wget http://pecl.php.net/filter/get
$ tar xzf filter-0.11.0
$ phpize
$ ./configure
$ make
$ make install

Then edit /etc/php.ini and add:

extension=filter.so

Restart the web server.

In case there is an error such as error: ext/pcre/php_pcre.h: No such file or directory, install file php_pcre.h in /usr/local/include/php/ext/pcre/ (or /usr/include/php5/ext/pcre):

/*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2006 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Andrei Zmievski <andrei@php.net>                             |
   +----------------------------------------------------------------------+
 */
 
/* $Id: php_pcre.h,v 1.44 2006/01/01 13:09:52 sniper Exp $ */
 
#ifndef PHP_PCRE_H
#define PHP_PCRE_H
 
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
 
#if HAVE_BUNDLED_PCRE
#include "pcrelib/pcre.h"
#else
#include "pcre.h"
#endif
 
#if HAVE_LOCALE_H
#include <locale.h>
#endif
 
PHP_FUNCTION(preg_match);
PHP_FUNCTION(preg_match_all);
PHP_FUNCTION(preg_replace);
PHP_FUNCTION(preg_replace_callback);
PHP_FUNCTION(preg_split);
PHP_FUNCTION(preg_quote);
PHP_FUNCTION(preg_grep);
 
PHPAPI char *php_pcre_replace(char *regex, int regex_len, 
  char *subject, int subject_len, 
  zval *replace_val, int is_callable_replace, 
  int *result_len, int limit, int *replace_count TSRMLS_DC);
PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC);
PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC);
 
extern zend_module_entry pcre_module_entry;
#define pcre_module_ptr &pcre_module_entry
 
typedef struct {
	pcre *re;
	pcre_extra *extra;
	int preg_options;
#if HAVE_SETLOCALE
	char *locale;
	unsigned const char *tables;
#endif
	int compile_options;
	int refcount;
} pcre_cache_entry;
 
PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len, 
   pcre_extra **extra, int *preg_options, int *compile_options  TSRMLS_DC);
 
ZEND_BEGIN_MODULE_GLOBALS(pcre)
	HashTable pcre_cache;
ZEND_END_MODULE_GLOBALS(pcre)
 
#ifdef ZTS
# define PCRE_G(v) TSRMG(pcre_globals_id, zend_pcre_globals *, v)
#else
# define PCRE_G(v)	(pcre_globals.v)
#endif
 
#else
 
#define pcre_module_ptr NULL
 
#endif /* HAVE_PCRE || HAVE_BUNDLED_PCRE */
 
#define phpext_pcre_ptr pcre_module_ptr
 
#endif /* PHP_PCRE_H */

SSL Certificate

For Apache, we need to get the following cert components:

  • Package with cert and private key (encrypted) in PKCS#12 or PFX format (extension .pfx or .p12):
     acme-cert-key-pair.pfx
  • Organization's cert (usually PEM format) (extension .crt or .pem):
     acme-cert-pem.crt
  • Organization's decrypted private key (extension .key):
     acme-decrypted.key
  • Cert Authority chain or bundle (extension .crt):
     gd_bundle.crt

Get PFX file from Certificate Authority (CA), then extract cert and private key (encrypted and decrypted). Eg. for organization Acme:

#!/bin/bash
#
# Export the private key file from the pfx file
echo "### Export the private key file from the pfx file"
openssl pkcs12 -in acme-cert-key-pair.pfx -nocerts -out acme-encrypted.key
 
# Remove the passphrase from the private key
echo
echo "### Remove the passphrase from the private key"
openssl rsa -in acme-encrypted.key -out acme-decrypted.key
 
# Export the certificate file from the pfx file
echo
echo "### Export the certificate file from the pfx file"
openssl pkcs12 -in acme-cert-key-pair.pfx -clcerts -nokeys -out acme-cert-pem.crt

NOTE: The PKCS#12 or PFX format is a binary format for storing the server certificate, any intermediate certificates, and the private key in one encryptable file. PFX files usually have extensions such as .pfx and .p12. PFX files are typically used on Windows machines to import and export certificates and private keys.

When converting a PFX file to PEM format, OpenSSL will put all the certificates and the private key into a single file. You will need to open the file in a text editor and copy each certificate and private key (including the BEGIN/END statments) to its own individual text file and save them as certificate.cer, CACert.cer, and privateKey.key respectively.

The PEM format is the most common format that Certificate Authorities issue certificates in. PEM certificates usually have extentions such as .pem, .crt, .cer, and .key. They are Base64 encoded ASCII files and contain “—–BEGIN CERTIFICATE—–” and “—–END CERTIFICATE—–” statements. Server certificates, intermediate certificates, and private keys can all be put into the PEM format.

Apache and other similar servers use PEM format certificates. Several PEM certificates, and even the private key, can be included in one file, one below the other, but most platforms, such as Apache, expect the certificates and private key to be in separate files. (Source: https://www.sslshopper.com/ssl-converter.html)

Edit /etc/apache2/sites-available/default-ssl to include:

#   A self-signed (snakeoil) certificate can be created by installing
#   the ssl-cert package. See
#   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
#   If both key and certificate are stored in the same file, only the
#   SSLCertificateFile directive is needed.
#
#--- Self-signed Certificate & Key ---
##SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
##SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

#--- CA-signed Certificate & Key ---
# Note: When Private Key is decrypted, it requires no password when restarting Apache
SSLCertificateFile    /etc/ssl/certs/acme-cert-pem.crt
SSLCertificateKeyFile /etc/ssl/private/acme-decrypted.key  
##SSLCertificateKeyFile /etc/ssl/private/acme-encrypted.key

#   Server Certificate Chain:
#   Point SSLCertificateChainFile at a file containing the
#   concatenation of PEM encoded CA certificates which form the
#   certificate chain for the server certificate. Alternatively
#   the referenced file can be the same as SSLCertificateFile
#   when the CA certificates are directly appended to the server
#   certificate for convinience.
#SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
SSLCertificateChainFile /etc/apache2/ssl.crt/ca-godaddy-bundle.crt

Restart Apache:

% /etc/init.d/apache2 restart

Verification

  • Check apache error logs. Eg:
    % tail -f /var/log/apache2/error.log
  • Check the website using https in the URL.
  • Check the padlock icon on the URL in the browser. Get information from certificate.
  • Visit SSL Labs and submit site to analyze security.

References

Obtaining Cert from Cert Authority (CA)

When getting a cert, a CA will request to submit a CSR file with the multiple domains that will be using the cert. This is how to create the CSR file using the SubjectAltName method in OpenSSL, assuming we need it to certify domains acme.com www.acme.com secure.acme.com:

Create an OpenSSL custom config file /etc/ssl/mycerts/openssl.cnf:

[ req ]
default_bits       = 2048
default_keyfile    = privkey.pem
distinguished_name = req_distinguished_name
req_extensions     = req_ext # The extentions to add to the self signed cert
 
[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = US
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Florida
localityName                = Locality Name (eg, city)
localityName_default        = Longwood
organizationName            = Organization Name (eg, company)
organizationName_default    = Acme, Inc.
commonName                  = Common Name (eg, YOUR name)
commonName_default          = www.acme.com
commonName_max              = 64
 
[ req_ext ]
subjectAltName = @alt_names
 
[alt_names]
DNS.1 = acme.com
DNS.2 = secure.acme.com

Generate the private key file

$ openssl genrsa -out acme.key 2048

Generate the CSR file

$ openssl req -new -newkey rsa:2048 -nodes -keyout acme.key -out acme.csr -config openssl.cnf

Verify CSR file

$ openssl req -text -noout -in acme.csr

Once you are happy with the settings in that file, you can submit it to the CA to generate the certificate for you.

See also:

SELinux

Turning on/off enforcing at boot time 2):

You can specify the SELinux mode using the configuration file /etc/sysconfig/selinux.

  # This file controls the state of SELinux on the system.
  # SELINUX= can take one of these three values:
  #       enforcing - SELinux security policy is enforced.
  #       permissive - SELinux prints warnings instead of enforcing.
  #       disabled - No SELinux policy is loaded.
  SELINUX=enforcing
  # SELINUXTYPE= type of policy in use. Possible values are:
  #       targeted - Only targeted network daemons are protected.
  #       strict - Full SELinux protection.
  SELINUXTYPE=targeted

Setting the value to enforcing is the same as adding enforcing=1 to your command line when booting the kernel to turn enforcing on, while setting the value to permissive is the same as adding enforcing=0 to turn enforcing off. Note that the command line kernel parameter overrides the configuration file.

However, setting the value to disabled is not the same as the selinux=0 kernel boot parameter. Rather than fully disabling SELinux in the kernel, the disabled setting instead turns enforcing off and skips loading a policy.

Samba

Running

Register the Samba service to run at server boot time:

$ /sbin/chkconfig --level 35 smb on

Run the Samba service:

$ /sbin/service smb start

Add samba users. For example:

$ cd /etc/samba
$ smbpasswd -a jdoe

NOTE: Make sure the samba user matches a Linux user, otherwise it will not create the samba user. If you do not wish to give the user shell access in Linux, just set the shell to /sbin/nologin.

Testing

Test by connecting a client machine to the Samba server.

Linux

$ smbclient -L //server1 -d 3

Windows

C:\> net view \\server1
C:\> net use \\server1\data
Enter the user name for 'server1': jdoe
Enter the password for server1: ****

To disconnect from the share:

C:\> net use \\server1\data /delete

Troubleshooting

If after providing username and password there is no successful connection, and the error log in /var/log/samba/machinename.log shows

[2006/08/14 14:01:54, 0] smbd/service.c:make_connection_snum(911)
 ' ''ShareName'' ' does not exist or permission denied when connecting to [''ShareName''] Error was Permission denied

then you must configure SELinux to allow Windows XP client machines to connect correctly to those shares. Perform the following:

Configuring SELinux - Sharing User Home Directories

Source: Nazin Blog 3)

If you only share user home directories in Samba, then simply configure SELinux to allow that. There are two steps:

  1. Tell SELinux to allow the Samba daemon to access the smbpasswd and secrets.tdb files. Set the context of the smbpasswd and secrets.tdb files (this is a one-time action):
  2.  $ chcon -t samba_secrets_t /etc/samba/smbpasswd
     $ chcon -t samba_secrets_t /etc/samba/secrets.tdb
  3. Tell SELinux that it can share home directories. Place this line in the booleans.local file (usually at /etc/selinux/targeted/booleans.local):
  4.   samba_enable_home_dirs=1

This solution works perfectly, but only when sharing just user home directories. When sharing other paths, this solution is incomplete. You would need to disable SELinux for Samba.

Disabling SELinux, but Only for Samba!

Source: Nazin Blog 4)

Although there might be other ways to configure SELinux to allow Samba to share other paths, a quick solution is to simply disable SELinux for the Samba daemon only.

Perform the following commands once:

  $ setsebool -P smbd_disable_trans 1
  $ /sbin/service smb restart

The setsebool command, with the -P option, will actually write this entry into the booleans.local file for you, to make it permanent.

MySQL

Start the mysql service:

$ /sbin/service mysqld start

Register the mysql service to start up at boot time:

$ /sbin/chkconfig --level 35 mysqld on

Create a password for root user:

$ /usr/bin/mysqladmin -u root password 'new-password'
$ /usr/bin/mysqladmin -u root -h server1.mydomain.com password 'new-password'

VNC Server

To connect to Linux's desktop remotely, use VNC Server on the Linux machine, and VNC Viewer on the client machine (Windows workstation).

On the Linux server, connect (ssh, telnet, etc.) with the desired user, then run the VNC Server:

$ vncserver
  • Give it a password to access.
  • Write down the display number: server1.example.com:1

On the client machine, you have a choice on how to connect:

  • Use the browser to access http://server1.example.com:5801/ using the password. Note: the number 1 means the display connection number, so if you connected as display 7, the port should be 5807.
  • Use the VNC Client software. For example:
    C:\Apps\VNC\> vncviewer.exe

Configure VNC to Load Automatically

Edit the file /etc/sysconfig/vncserver to include all the users and their respective display settings. For example, we want the vncserver to boot automatically for users mayr and joel with displays 2 and 3 respectively, we would do the following:

#
# /etc/sysconfig/vncserver
#
#The VNCSERVERS variable is a list of display:user pairs.
# separated by spaces, eg: VNCSERVERS="1:joe 2:jill"
#
# Uncomment the line below to start a VNC server on display :1
# as my 'myusername' (adjust this to your own). You will also
# need to set a VNC password; run 'man vncpasswd' to see how
# to do that.
#
# DO NOT RUN THIS SERVICE if your local area network is
# untrusted! For a secure way of using VNC, see
# <URL:http://www.uk.research.att.com/vnc/sshvnc.html>.

VNCSERVERS="1:jsmith 2:jdoe"

Configure VNC to run GNOME/KDE as desktop

Startup settings: edit the file ~/.vnc/xstartup

#!/bin/sh
# Linux VNC session startup script
unset SESSION_MANAGER
vncconfig -iconic &
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
xterm -geometry 80x50+510+10 -ls -title "$VNCDESKTOP Desktop" &
xterm -geometry 80x24+10+350 -ls -title "$VNCDESKTOP Desktop" -bg black -fg white &
exec /etc/X11/xinit/xinitrc

Configure VNC to run TWM (Tom's Window Manager) as desktop

Startup settings: edit the file ~/.vnc/xstartup

#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
xterm -geometry 80x50+510+10 -ls -title "$VNCDESKTOP Desktop" &
xterm -geometry 80x24+10+350 -ls -title "$VNCDESKTOP Desktop" -bg black -fg white &
twm &

Stop a VNC session

Stop a VNC session (assuming it is in display :1) :

$ vncserver -kill :1

GUI Desktops

You can switch between the following desktops:

  • enlightenment
  • fluxbox
  • fvwm
  • gnome
  • icewm
  • kde
  • toplevel
  • twm
  • wmaker
  • xfce

Use the switchdesk command. For example:

 $ switchdesk kde

Firewall

Enable the the iptables firewall, and use the /etc/rc.d/arno-iptables-firewall to tighten security. First, edit the file /etc/arno-iptables-firewall.conf:

# Put in the following variables which ports or IP protocols you want to leave
# open to the whole world.
# -----------------------------------------------------------------------------
OPEN_TCP="22 80"
OPEN_UDP="22 80"
OPEN_IP=""
OPEN_ICMP=0

Run the script /etc/rc.d/arno-iptables-firewall to start it:

 $ cd /etc/rc.d/
 $ ./arno-firewall-script.sh restart

Uncomplicated Firewall (UFW) in Ubuntu

  • Enable ufw:
    % ufw enable
  • Add rules:
    % ufw default deny
    % ufw allow to any port 80                                 # http
    % ufw allow to any port 443                                 # https
    % ufw allow from 192.168.0.0/24 to any port 22             # ssh
    % ufw allow from 192.168.0.0/24 to any port 25             # smtp
    % ufw allow from 192.168.0.0/24 to any port 123            # ntp
    % ufw allow from 192.168.0.0/24 to any port 143            # imap
    % ufw allow from 192.168.0.0/24 to 192.168.0.149 port 465  # smtp over SSL
    % ufw allow from 192.168.0.0/24 to any port 53             # dns
    % ufw allow from 192.168.0.0/24 to any port 67             # dhcp server
    % ufw allow from 192.168.0.0/24 to any port 68             # dhcp client
    % ufw allow proto udp from 192.168.0.0/24 to 192.168.0.149 port 137  # samba NetBIOS Name Service
    % ufw allow proto udp from 192.168.0.0/24 to 192.168.0.149 port 138  # samba NetBIOS Datagram Service
    % ufw allow from 192.168.0.0/24 to any port 139                      # samba NetBIOS Session Service
    % ufw allow from 192.168.0.0/24 to any port 445                      # samba SMB file sharing
    % ufw allow from 192.168.0.0/24 to 192.168.0.31 port 3690    # Subversion server using ip 192.168.0.31
  • Delete rules:
    % ufw delete allow to any port 80   # delete http rule

MediaWiki

Installation

$ tar xzvf mediawiki-x.x.x.tar.gz

  • Create MySQL database and user:
mysql> create database wikidb;
mysql> grant create, select, insert, update, delete, lock tables on wikidb.* to wiki@localhost identified by 'password';
mysql> flush privileges;

Configuration

Disable certain users from editing pages, and enabling others. Add the following lines to MediaWiki/LocalSettings.php:

# Disable anonymous and regular users from editing pages
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['user']['edit'] = false;
 
# Enable 'swdev' group members to edit pages.
# Add new groups here, just like 'swdev'.
$wgGroupPermissions['swdev']['edit'] = true;

To change which groups a user belongs to, login as Admin and visit Special:Specialpages and click the link to 'User Rights Management' on the very bottom of the list which will bring them to Special:Userrights and follow the on-screen instructions.

Troubleshooting

Getting a blank screen after posting an edit or uploading an image file

  • Check the limit of settings upload_max_filesize and post_max_size in file /etc/php.ini.
  • Under Fedora and Apache, this problem happens with large files. Fix it by increasing the memory limits in MediaWiki/LocalSettings.php:
ini_set( 'memory_limit', '20M' ); # You might need to increase the limit

Sendmail

Mail Spool

Directory permissions for /var/spool/mail should be drwxrwxr-x for group mail (in case it is not working). Otherwise, it will have trouble sending mail.

Configuration

Verify version of Sendmail:

$ sendmail -d0.1 -bt < /dev/null

Default Sendmail Settings for Receiving Mail

The default configuration for Sendmail does not allow for the receiving of mail except from yourself (localhost). To receive mail, perform the following operations:

  • Backup the files /etc/mail/sendmail.mc and /etc/mail/sendmail.cf
  • Edit the file /etc/mail/sendmail.mc and change/comment the line DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA') to display:
 dnl DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA') 
  • Sendmail will then use the default which allows it to receive mail from other systems.

Mail Relay

Setup mechanism for mail relay. Choose one of the following (be careful with the quotes ` ' ):

  FEATURE(`relay_entire_domain')dnl      <-- domain names must be added to /etc/mail/access
  FEATURE(`relay_hosts_only')dnl         <-- hosts names (FQDN) must be added to /etc/mail/access

Run this command to regenerate sendmail.cf:

 $ m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf

Edit files /etc/mail/local-host-names. It contains all of the alternate host names of the server. (i.e. domain-name.com) Sendmail will not accept mail for a domain unless it is permitted to do so by the contents of this file.

  #--- /etc/mail/local-host-names ---
  example.com
  mail.example.com
  10.10.10.2

Create /etc/mail/access and /etc/mail/relay-domains to add domains and handle mail for those domains. Otherwise, the anti-spam configuration will only honor local mail and refuse any other.

  #--- /etc/mail/access ---
  localhost.localdomain   RELAY
  localhost               RELAY
  127.0.0.1               RELAY
  example.com             RELAY
  192.168.                RELAY
  #--- /etc/mail/relay-domains ---
  example.com             RELAY_FROM
  mail.example.com        RELAY_FROM
  pc01.example.com        RELAY_FROM
  dsl01.cableco.com       RELAY_FROM
  10.10.10.2              RELAY_FROM
  192.168.0.              RELAY_FROM

Regenerate hash tables by typing:

$ makemap hash /etc/mail/access < /etc/mail/access
$ makemap hash /etc/mail/relay-domains < /etc/mail/relay-domains

Run and Test Sendmail

Restart the sendmail service:

 $ /sbin/service sendmail restart 

Test sendmail with verbose mode:

 $ date | sendmail -v jdoe@hotmail.com 

Blocking Spam and Unwanted Relaying

Edit the file /etc/mail/access to include:

  #--- /etc/mail/access ---
  from:nobody           REJECT
  from:apache           REJECT
  from:apache@localhost REJECT
  apache@               REJECT
  apache@localhost      REJECT

Remove unsafe copies of /cgi-bin/formmail.pl. It allows external users to send mail as nobody@localhost or apache@locahost. Do a security audit on users' cgi programs, and you might find one with a vulnerablity. If you must use one, install one you can trust in a common cgi-bin, and instruct users on how to use it.

Mail Aliases

  • Directory permission for /var/spool/mail should be drwxrwxr-x for group mail. Otherwise, it will have trouble sending mail.
  • Global aliases (file /etc/aliases): Various error messages in the system will normally be issued as internal email. To ensure that these will actually be read, one should create an /etc/aliases. An example that should cover most eventualities is:
 #
 # /etc/aliases
 # format:  alias: name
 #
 postmaster: root
 ftp: root
 news: root
 usenet: root
 faxmaster: root
 fax: root
 webmaster: root
 mailer.daemon: root
 support: superadmin, jsmith
 acctng: jdoe, jsmith
  • Recreate aliases database. Remember to issue the command newaliases every time you change /etc/aliases.
 $ newaliases 

Mail Routing

In the DNS database entry for example.com (file /etc/named/example.com.hosts), include the proper MX record. This is a slightly different example compared to the DNS file shown above (see DNS Configuration):

  ;
  ; Zone file for example.com
  ;
  ; domain = example.com
  ; host   = server1.example.com
  ; e-mail = root@example.com
  ;
  @           IN SOA example.com. root.example.com. ( 
                         20010016 ; Serial
                         8H ; Refresh
                         2H ; Retry
                         1W ; Expire
                         1D) ; Minimum TTL
                    TXT    "Sample DNS Server"
                    NS example.com.       ; internet address of name server
                    MX 10 example.com.    ; primary mail exchanger
  ;
  localhost     A    127.0.0.1
  router        A    200.35.85.89
  ns            A    200.35.85.90
  www           A    200.35.85.90
  mail          A    200.35.85.90
  pop           A    200.35.85.90
  server1       A    192.168.1.2
  ftp           A    192.168.1.2

Add the domain name to the /etc/hosts file in the line where the mail host is found. This is done because of mail looping occurs when the DNS zone (see above zone definition /etc/named/example.com.hosts) has the same mail hosts as the hosts being defined. Here server1, mail, and example.com are the same, so looping will occur and delivery of messages will not occur. Eg: server1.example.com is the mail server in this case so:

#
# /etc/hosts
#

# For loopbacking.
127.0.0.1      localhost
200.35.85.90   www.example.com www mail.example.com mail example.com
192.168.1.2    server1.example.com server1 example.com

# End of hosts.

InterNetNews (INN) Server

Configuration

Configure the server. Edit the following files: /etc/news/expire.ctl

 # Keep local newsgroup 3 months (server1.example.com).
 server1.*:A:3:90:90

/etc/news/nnrp.access

##  nnrp.access - access file for on-campus NNTP sites
##  Format:
##      <host>:<perm>:<user>:<pass>:<groups>
##  Connecting host must be found in this file; the last match found is
##  used, so put defaults first.
##      <host>          Wildcard name or IP address
##      <perm>          R to read; P to post
##      <user>          Username for authentication before posting
##      <pass>          Password, for same reason
##      <groups>        Newsgroup patterns that can be read or not read
##  To disable posting put a space in the <user> and <pass> fields, since
##  there is no way for client to enter one.
##
## Default is no access, no way to authentication, and no groups.
*:: -no- : -no- :!*
##  Foo, Incorporated, hosts have no password, can read anything.
*:Read Post:::spinnaker*
localhost:Read Post:::*
server1.example.com:Read Post:::*

Run service:

$ /sbin/service innd start
$ /sbin/chkconfig --level 35 innd on

Security (Giving Access)

Disable SELinux protection:

$ setsebool -P innd_disable_trans 1
$ /sbin/service innd restart

Edit the permissions file /etc/news/readers.conf to enable local machines to read/post:

# This auth group matches all connections from example.com or machines in
# the example.com domain and gives them the identity <local>@example.com.
# Instead of using wildmat patterns to match machine names, you could also
# put a wildmat pattern matching IP addresses or an IP range specified
# using CIDR notation (like 10.10.10.0/24) here.

auth "local" {
    hosts: "*.example.com, example.com, 192.168.0.0/24"
    default: "<local>@example.com"
}
. . .
# Now for the access groups.  All of our access groups should have users:
# parameters so there are no access groups that match connections without
# an identity (such as are generated by the "abusers" entry above).
# First, the default case of local users, who get to read and post to
# everything.

access "local" {
    users: "<local>@example.com"
    newsgroups: "*"
}

Creating Local Newsgroup

To create a local news group, perform the following steps:

  1. Make sure service innd is running.
  2. Add an entry for the new local group in /etc/news/expire.ctl, (in the site directory, then make install).
  3. Add a descriptive entry to newsgroups. Lock the /var/lib/news/newsgroups file, using shlock, and append the newsgroup description to the file. The following example seems to function:
     $ shlock -f /var/lib/news/LOCK.newsgroups -p $$ && 
    echo "examplesite.class.bskt201<tab>Introductory Basket Weaving" >> /var/lib/news/newsgroups && 
    rm /var/lib/news/LOCK.newsgroups 
  4. Finally, the group can be added with the command:
    $ /usr/lib/news/bin/ctlinnd newgroup examplesite.dept.news.group m "John Doe (Mod)" 
  5. Add entries to /etc/news/newsfeeds to restrict the local groups to your organization:
    ME:!local.*::
    
    out.going.site:*,!local.*:Tf,Wnm:

Please consider, that local is a very common name for local groups, so if a user crossposts to local.test and misc.test the article will show up in all local.test over the world. So please choose a 'better' name.

Further Reading

Backup Critical Data and Configuration

Create a daily cron task to backup some important files to a directory (for example: /data/backup). This script should be created as /etc/cron.daily/backup.sh:

#!/bin/bash
## script: /etc/cron.daily/backup.sh
##
 
## removes old backup file
rm -rf /data/backup/*
 
## backup the following directories:
tar -czvf /data/backup/mail-backup.tar.gz /var/spool/mail
tar -czvf /data/backup/home-backup.tar.gz /home
tar -czvf /data/backup/website-backup.tar.gz /var/www/html
tar -czvf /data/backup/mysql-data-backup.tar.gz /var/lib/mysql
tar -czvf /data/backup/etc-dir.tar.gz /etc
 
## send reminder to sysadmin to pull the tarball from the server.
mail root -s "Get the backup tarball off the server"

sudo Configuration

Source: Quick HOWTO: Linux Users and Sudo 5)

Use sudo when several administrators maintain a system. This allows access to the right people without giving away full root access, and losing track of what changes were done by whom.

Obtaining root Privileges

$ sudo more /etc/sudoers

Becoming root Using a Regular User

The su command allows a regular user to become the system's root user if they know the root password. A user with sudo rights to use the su command can become root, but they only need to know their own password, not that of root as seen here.

jdoe@example.com:~$ sudo su -
Password:
root@example.com:~#

Some systems administrators will use sudo to grant root privileges to their own personal user account without the need to provide a password.

Creating sudo users

Use this special text editor that is used to edit the /etc/sudoers configuration file:

$ visudo

Creating /etc/sudoers file

File format:

usernames/group servername = (usernames command can be run as) command

Guidelines:

There are some general guidelines when editing this file:

  • Groups are the same as user groups and are differentiated from regular users by a % at the beginning. The Linux user group “users” would be represented by %users.
  • You can have multiple usernames per line separated by commas.
  • Multiple commands also can be separated by commas. Spaces are considered part of the command.
  • The keyword ALL can mean all usernames, groups, commands and servers.
  • If you run out of space on a line, you can end it with a back slash (\) and continue on the next line.
  • sudo assumes that the sudoers file will be used network wide, and therefore offers the option to specify the names of servers which will be using it in the servername position. In most cases, the file is used by only one server and the keyword ALL suffices for the server name.
  • The NOPASSWD keyword provides access without prompting for your password.

Simple /etc/sudoers Examples

This section presents some simple examples of how to do many commonly required tasks using the sudo utility.

Granting All Access to Specific Users

You can grant users jdoe and jsmith full access to all privileged commands, with this sudoers entry.

jdoe, jsmith  ALL=(ALL) ALL

This is generally not a good idea because this allows jdoe and jsmith to use the su command to grant themselves permanent root privileges thereby bypassing the command logging features of sudo. The example on using aliases in the sudoers file shows how to eliminate this problem.

Granting Access To Specific Users To Specific Files

This entry allows user peter and all the members of the group operator to gain access to all the program files in the /sbin and /usr/sbin directories, plus the privilege of running the command /usr/local/apps/check.pl. Notice how the trailing slash (/) is required to specify a directory location:

peter, %operator ALL= /sbin/, /usr/sbin, /usr/local/apps/check.pl

Notice also that the lack of any username entries within parenthesis () after the = sign prevents the users from running the commands automatically masquerading as another user. This is explained further in the next example.

Granting Access to Specific Files as Another User

The sudo -u entry allows allows you to execute a command as if you were another user, but first you have to be granted this privilege in the sudoers file.

This feature can be convenient for programmers who sometimes need to kill processes related to projects they are working on. For example, programmer peter is on the team developing a financial package that runs a program called monthend as user accounts. From time to time the application fails, requiring “peter” to stop it with the /bin/kill, /usr/bin/kill or /usr/bin/pkill commands but only as user “accounts”. The sudoers entry would look like this:

peter ALL=(accounts) /bin/kill, /usr/bin/kill /usr/bin/pkill

User peter is allowed to stop the monthend process with this command:

[peter@bigboy peter]# sudo -u accounts pkill monthend

Granting Access Without Needing Passwords

This example allows all users in the group operator to execute all the commands in the /sbin directory without the need for entering a password. This has the added advantage of being more convenient to the user:

%operator ALL= NOPASSWD: /sbin/

Using Aliases in the sudoers File

Sometimes you'll need to assign random groupings of users from various departments very similar sets of privileges. The sudoers file allows users to be grouped according to function with the group and then being assigned a nickname or alias which is used throughout the rest of the file. Groupings of commands can also be assigned aliases too.

In the next example, users peter, jdoe and jsmith and all the users in the operator group are made part of the user alias ADMINS. All the command shell programs are then assigned to the command alias SHELLS. Users ADMINS are then denied the option of running any SHELLS commands and su:

Cmnd_Alias    SHELLS = /usr/bin/sh,  /usr/bin/csh, \
                       /usr/bin/ksh, /usr/local/bin/tcsh, \
                       /usr/bin/rsh, /usr/local/bin/zsh
 
 
User_Alias    ADMINS = peter, bob, bunny, %operator
ADMINS        ALL    = !/usr/bin/su, !SHELLS

This attempts to ensure that users don't permanently su to become root, or enter command shells that bypass sudo's command logging. It doesn't prevent them from copying the files to other locations to be run. The advantage of this is that it helps to create an audit trail, but the restrictions can be enforced only as part of the company's overall security policy.

Using syslog To Track All sudo Commands

All sudo commands are logged in the log file /var/log/messages which can be very helpful in determining how user error may have contributed to a problem. All the sudo log entries have the word sudo in them, so you can easily get a thread of commands used by using the grep command to selectively filter the output accordingly.

Here is sample output from a user jdoe failing to enter their correct sudo password when issuing a command, immediately followed by the successful execution of the command /bin/more sudoers.

[root@example.com/tmp]# grep sudo /var/log/messages
Nov 18 22:50:30 example.com sudo(pam_unix)[26812]: authentication failure; logname=jdoe uid=0 euid=0 tty=pts/0 ruser= rhost= user=jdoe
Nov 18 22:51:25 example.com sudo: jdoe : TTY=pts/0 ; PWD=/etc ; USER=root ; COMMAND=/bin/more sudoers
[root@example.com/tmp]#

rsync Server to Backup/Mirror Hosts

Server Setup

Setup the following files on the server.

  • Configuration file. File /etc/rsyncd.conf:
    # File /etc/rsyncd.conf
    motd file = /etc/rsyncd.motd
    log file = /var/log/rsyncd.log
    pid file = /var/run/rsyncd.pid
    lock file = /var/run/rsync.lock
     
    [webfiles]
       path = /var/www/t/test
       comment = Audina RSync Server (temp webserver)
       uid = www-data
       gid = www-data
       read only = yes
       list = yes
       auth users = root,jdoe,webmirror
       secrets file = /etc/rsyncd.scrt
       hosts allow = 192.168.0.0/24
  • The Message of the Day. File /etc/rsyncd.motd:
    Welcome to Audina's RSync server (temp webserver)
  • Secrets or password file. File /etc/rsyncd.scrt:
    # File /etc/rsyncd.scrt
    # rsyncd password file
    # username:password (not same username/password as system)
    root:interestingpass
    jdoe:asyncpass
    webmirror:mywebsyncpass
  • Start rsync as a daemon (service):
    % rsync --daemon --config=/etc/rsyncd.conf 

Client

  • Setup and run a client script to launch a connection to the server:
    #!/bin/bash
    # File /root/getwebfiles.sh
    # Example: Get files from server 192.168.0.149 (source) to local directory /data/mirror/webserver/www (destination)
    #rsync --verbose  --progress --stats --compress --rsh=/usr/bin/ssh \
    #      --recursive --times --perms --links --delete \
    #      --exclude "*bak" --exclude "*~" \
    #      192.168.0.149::webfiles /var/www/mirror
    rsync --archive --verbose --progress --stats --rsh=/usr/bin/ssh --recursive --times --perms --links --delete 192.168.0.149::webfiles /data/mirror/webserver/www
  • Connect to server, type ssh password, then when connected, type rsync password if it prompts for it (when using auth users directive in server side /etc/rsyncd.conf file).

rsynce References

Spyware/Malware Detection

  • Install chkrootkit and rkhunter. Refer to How to check Linux rootkits with detector software.
  • Use IP address check sites:
    • StopForumSpam: Eg: check like this
      http://www.stopforumspam.com/api?ip=216.24.206.59&f=json"

      or with script spamcheck.php:

      <?php
      $url = "http://www.stopforumspam.com/api?ip=".$_GET["ip"]."&f=json";
      $data = file_get_contents($url);
      $results = json_decode($data, true);
       
      print $results["ip"]["frequency"];
      //print_r($results);
      ?> 

      Call it by:

      http://www.example.com/spamcheck.php?ip=68.65.109.27
    • BotScout.com: Eg:
      http://www.botscout.com/ipcheck.htm?ip=216.24.206.59
  • Check out what is monopolizing the CPU time (Refer to CPU Utilization):
    % ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10
    OR
    % ps -eo pcpu,pid,user,args | sort -r -k1 | less

NTP Server

ntpdate

  • Create a file /etc/cron.daily/ntpdate containing:
    ntpdate ntp.ubuntu.com
  • The file /etc/cron.daily/ntpdate must also be executable.
    % sudo chmod 755 /etc/cron.daily/ntpdate
  • Update the time on the server:
    % ntpdate -u ntp.ubuntu.com pool.ntp.org 

ntpd

  • Setup ntpd:
    % sudo apt-get install ntp
  • Edit /etc/ntp.conf to include servers to connect:
    server ntp.ubuntu.com
    server pool.ntp.org
  • Add firewarll rule (iptables) to allow incoming queries from clients trying to synchronize to this server:
    % iptables -A INPUT -p udp --dport 123 -j ACCEPT
    % iptables -A OUTPUT -p udp --sport 123 -j ACCEPT

DNS Server (BIND9)

Master

  • Install DNS server BIND9:
    % apt-get install bind9 bind9-doc bind9utils

Slave

  • Add range to be allowed in transfer zones. Edit file /etc/bind/named.conf.options:
    options {
      directory "/etc/bind";
      // If there is a firewall between you and nameservers you want
      // to talk to, you may need to fix the firewall to allow multiple
      // ports to talk. See http://www.kb.cert.org/vuls/id/800113
      // If your ISP provided one or more IP addresses for stable
      // nameservers, you probably want to use them as forwarders.
      // Uncomment the following block, and insert the addresses replacing
      // the all-0's placeholder.
      // forwarders {
      //       0.0.0.0;
      // };
      # add a range you allow to transfer zones
      allow-transfer { localhost; 192.168.0.0/24; };
    
      auth-nxdomain no; # conform to RFC1035
      listen-on-v6 { none; };
    };
  • Add slave zone to file /etc/bind/named.conf.default-zones:
    // slave zone.  Check transfer with: % dig @192.168.0.104 acme.com. axfr
    zone "acme.com" {
            type slave;
            masters { 192.168.0.104; 192.168.0.101; };
            file "/etc/bind/slaves/acme.com";
    };
  • Create directory /etc/bind/slaves:
    % mkdir /etc/bind/slaves
    % chmod g+w /etc/bind/slaves
    % chown -R bind:bind /etc/bind/slaves
  • Enable UFW firewall:
    % ufw enable
    % ufw allow to any port 80                      # http 
    % ufw allow from 192.168.0.0/24 to any port 53  # dns
    % ufw allow from 192.168.0.0/24 to any port 22  # ssh
    % ufw allow from 192.168.0.0/24 to any port 67  # dhcp server
    % ufw allow from 192.168.0.0/24 to any port 68  # dhcp client
    % ufw status
  • Add permissions:
    • AppArmor: Edit file /etc/apparmor.d/usr.sbin.named and add:
      /etc/bind/slaves/** rw,
      /etc/bind/slaves/ rw,
    • Enable zone transfer on master server. In Windows server: DNS > <ServerName> > Forward Lookup Zones > <domainname>, and select properties (right-click on domain name). Select 'Zone Transfers' tab, and 'Allow zone transfer' > 'Only to the following servers' > <IP address of slave dns server> (eg: 192.168.0.104). Repeat these steps with the 'Notify' button in the same screen.
  • Restart BIND9:
    % /etc/init.d/bind9 restart
  • Check slave zone transfer (assuming master server is 192.168.0.104):
    % dig @192.168.0.2 acme.com. axfr

Fixing Ethernet Card not Detected on Ubuntu Server

When moving hard drives to new hardware, it might happen that network cards are not being detected, thus losing network access. To fix this:

  • Edit file /etc/udev/rules.d/70-persistent-net.rules
  • Comment out all network cards defined there
  • Reboot server

Sample /etc/udev/rules.d/70-persistent-net.rules file:

# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.
 
# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:1e.0/0000:02:08.0 (e100)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:07:e9:3c:34:1f", 
    ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
 
# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0/0000:02:01.0 (e1000)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:07:e9:3c:34:1f", 
    ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
Security

Cleaning Hacked Server

Run these tools to find injected code in PHP files, then edit the files to remove offending code (NOTE: injection code might not be obvious…it sits at the end of a long line after many spaces, typically the first php line), or simply delete those files (if no useful code belongs to your site):

$ cd /var/www
$ find . -name "*.php" -exec grep -H "eval(" {} \;

Hacked scripts tend to have injected code that looks like this:

  eval($p38d[$GLOBALS['y110d20'][21]]);

Look for odd and generic filenames, such as

info.php
sql.php
dir.php
files.php
start.php
plugin0.php
error.php
htaccess

Also, search all files for a condition:

$ egrep -Rl 'function.*for.*strlen.*isset' /var/www
$ egrep -Rl '\$GLOBALS.*\\x' /var/www
$ egrep -Rl 'isset.*eval' /var/www
$ egrep -Rl 'PHPMailer' /var/www
$ egrep -Rl 'encodeURIComponent' /var/www
$ egrep -Rl 'se_referrer' /var/www
$ egrep -Rl 'base64_decode' /var/www
$ find /var/www -newermt "yyyy-mm-dd"

Search all PHP files for a condition:

$ find /home/*/public_html/ -type f -name "*php" -exec egrep -l '\$GLOBALS.*\\x|function.*for.*strlen.*isset' "{}" \;
$ find /var/www -type f -name "*php" -exec egrep -l 'se-referrer' "{}" \;
$ find /var/www -type f -name "*php" -exec egrep -l 'base64_decode' "{}" \;
$ find /var/www -type f -name "*php" -exec egrep -l '<iframe' "{}" \;

To find files already tagged as suspected by the operating system, use this command:

$ cd /var/www
$ find . -name "*.php.suspected"

Check mail queue (sendmail or postfix) to make sure we are not spamming:

$ cd /var/spool/mqueue
$ ls -la
$ cd /var/spool/mqueue-client
$ ls -la

Disable sendmail if necessary until the server has been cleaned. Try one of these:

$ /etc/init.d/sendmail stop
$ service sendmail stop

For a WordPress site, check database records for fishy code:

SELECT * FROM wp_posts WHERE post_content LIKE '%<iframe%'
  UNION
  SELECT * FROM wp_posts WHERE post_content LIKE '%<noscript%'
  UNION
  SELECT * FROM wp_posts WHERE post_content LIKE '%display:%'
 
SELECT * FROM `wp_options` WHERE `option_name` LIKE '%srb_%'
DELETE FROM `wp_options` WHERE `option_name` LIKE '%srb_%'
 
DELETE FROM wp_options 
  WHERE option_name LIKE '_transient_%' 
  OR option_name LIKE 'displayed_galleries%'

In WordPress, query for unauthorized admin accounts:

SELECT u.ID, u.user_login FROM wp_usermeta m, wp_users u 
   WHERE m.meta_key = 'wp_user_level' 
   AND m.meta_value = 10 
   AND m.user_id = u.ID
 
/* Delete unauthorized user with user_id = 312 */
DELETE FROM wp_usermeta WHERE user_id = 312
DELETE FROM wp_users WHERE ID = 312

Check the syslog to see if emails are being sent that are not supposed to:

$ tail -f /var/log/mail.log

Force any login to use HTTPS. Add a redirect for login in .htaccess file:

RewriteCond %{HTTPS} off
RewriteRule ^login$ https://www.acme.com/login [R=301,L]

Check for clean site, visiting this site:

Follow these other instructions to clean a hacked site:

References:

References