One of the less known functionalities implemented in the Linux kernel is the Magic SysRq key. Initially implemented as a debugging feature for kernel development it has also made its way into system administration use and the /proc filesystem.
Basically the Magic SysRq keys are low level commands that can be sent to the kernel regardless of a system’s state. That being said it can be most useful in extreme cases where the system is not responding to do a reboot, unmount partitions or sync the partitions (flush their write buffer to disk).
Before being able to actually use this, you have to enable the SysRq keys:
echo “1″ > /proc/sys/kernel/sysrq
All these commands can be sent to the kernel using the combination:
or by piping the key to the /proc filesystem:
echo [key] > /proc/sysrq-trigger
The SysRQ key on the keyboard can usually be found on the same key as “PrintScreen”.
A full list of the commands that can be sent can be found on Wikipedia.
Now you ask yourself, when would I use this? Let’s take the most common example: a server that has become completely unresponsive and the only solution would be to reboot it. But that server hosts a database with precious information and you do not know if all the information kept in memory by the database has been written to disk or if the sudden reboot would trigger errors and inconsistencies on the filesystem. The Magic SysRQ keys would come in handy now:
- gracefully terminate all running processes except init (PID1):
or
echo “e” > /proc/sysrq-trigger
- kill all the stubborn processes:
or
echo “k” > /proc/sysrq-trigger
- sync all mounted filesystems – meaning flush all the memory buffers to disk:
or
echo “s” > /proc/sysrq-trigger
- re-mount all partitions as read-only:
or
echo “u” > /proc/sysrq-trigger
- finally tell the box to immediately reboot:
or
echo “b” > /proc/sysrq-trigger
The case above is the most common one, but there are other times on the SysRq keys might come in handy. Let’s say you have accidentally deleted something from an ext2/3/4 partition. We know that on those filesystems the data isn’t immediately removed from the drive, but marked as deleted and will be overwritten the next time a process tries to write somewhere on the disk. Before you can use tools to un-delete – we will cover that in the next episode – we can tell the kernel to force re-mount all partitions as read-only, including the / partition:
or
echo “u” > /proc/sysrq-trigger
Now we can be sure that no process will overwrite our precious data and use some tool to recover the metadata.
Ever wanted to run certain packages from one version of the operating system ( in this case Debian ) without having to upgrade (or downgrade) the entire system ?
Well, the “Pin” option in the Apt package management system lets you do that. It’s pretty simple too!
1. Add the repositories for the two versions you want to have packages from in /etc/apt/sources.list . In this example we have Debian Stable and Testing:
#Stable
deb http://ftp.us.debian.org/debian stable main non-free contrib
deb http://non-us.debian.org/debian-non-US stable/non-US main contrib non-free
#Testing
deb http://ftp.us.debian.org/debian testing main non-free contrib
deb http://non-us.debian.org/debian-non-US testing/non-US main contrib non-free
Run apt-get update to add the repositories to apt.
2. Next, modify the file /etc/apt/preferences. This is where the actual “pinning” takes place. By default, apt installs the highest version available. So let’s say we would have the two repositories and we would like to install the package “dovecot-common”. Apt will take the highest version of that package which is naturally available in the “Testing” repository. But say we wanted to run the older of version of “dovecot-common” (for our own reasons, doesn’t matter why), which is available in the “Stable” repository. We would have this in our /etc/apt/preferences file:
Package: dovecot-common
Pin: release a=stable
Pin-Priority: 700
Package: dovecot-common
Pin: release a=testing
Pin-Priority: 600
Notice that we have a higher priority number for “dovecot-common” in the “stable” release. In Apt, the package with the highest priority wins, no matter the package version.
So now that you know this, you can use it to mix-match between packages from different repositories, while using strictly apt, no forcing of install and keeping them updated (if a newer version appears in that repository, apt will install it).
We have recently upgraded our mail servers running Debian Etch to Lenny and noticing that Dovecot 1.2 has been backported to Lenny backports, we decided to upgrade to Dovecot to take advantage of its fixes, improved security and quota settings.
Setting up quotas and warnings for any Dovecot above 1.0 is very simple.
1) First step is to enable the quota plugin for all protocols enabled in Dovecot ( pop3, imap and lda if you use it). This is done by just adding the line:
mail_plugins = quota
and for the IMAP protocol:
mail_plugins = quota imap_quota
2) Setup the plugin:
# Quota plugin settings
plugin {
quota = maildir:User quota
#Quota limit is 1GB
quota_rule = *:storage=1G
#We add 100Mb more for Trash
quota_rule2 = Trash:storage=100M
#We set up warnings at 75% and 90%
quota_warning = storage=75%% /opt/mail.sh 75 %u
quota_warning2 = storage=90%% /opt/mail.sh 90 %u
}
We can add as many rules and warnings as we want, just by adding and incrementing a number at the end of the warning or rule ( like above: quota_rule, quota_rule2 and so on ).
The first variable, “quota”, is the quota root and is a name that is sent to the IMAP client and can be anything you want.
The second variable is the quota itself and you can set it up using several limits: storage,bytes,messages,backend and ignore (this ignores quota for a specific mailbox). All variables support besides numbers the b/k/M/G/T/% suffixes. For example: 100M, 1G, 30% and so on.
The third variable sets up the quota warning. Using the limit you set up above in the rule you set up the warning at what level you want, by using a fixed number or percent. In the above example we used percent. In this case you need the double % ( %% ) so it can be escaped by dovecot. After the warning limit is set, in the same line, separated by space, is the command to run when that limit is reached. In this case it is a custom script that takes two command line arguments: the first one is the percent and the second one is the user that has reached the limit and to which to send the warning.
We set up the second argument (the user) as dovecot’s %u variable which is set in the ldap configuration, in the filter string. You can make this anything you want, taking the user dynamically through whichever system you have configured as your user database and whichever variable you have set up as you user.
For example, in my dovecot-ldap.conf this is what we have:
pass_filter = (&(objectClass=person)(userPrincipalName=%u))
and this is where I take my %u from.
And finally this is the script I use to send the warning. It uses the default sendmail binary, a simple text file and the two arguments taken from the command line:
#!/bin/bash
PERCENT=$1
USER=$2
echo “From: postmaster@domain.org
To: $USER
Subject: Your email quota is $PERCENT% full
Content-Type: text/plain; charset=”UTF-8″
This is an automatic message to warn that your mailbox is now $PERCENT% full.” > /tmp/quota.email.$USER
cat /tmp/quota.email.$USER | /usr/sbin/sendmail -f postmaster@domain.org $USER
rm /tmp/quota.email.$USER
That’s it! Whenever the user reaches its defined quotas he / she will receive a warning email. This quota are global, any user will have the same quota. If you want per-user quotas and / or soft-quotas check out my later edit below!
LATER EDIT:
If you want to make your quotas non-enforcing, that means the user will still receive the warnings but if he or she reaches the quota, their e-mails will not be blocked and they will still be able to receive, you must modify your “quota” variable in the plugin’s settings (the quota root). Make your settings look like this:
# Quota plugin settings
plugin {
quota = dict:user::noenforcing:file:/opt/data/mailboxes/%u/Maildir/dovecot-quota
#Quota limit is 1GB
quota_rule = *:storage=1G
#We add 100Mb more for Trash
quota_rule2 = Trash:storage=100M
#We set up warnings at 75% and 90%
quota_warning = storage=75%% /opt/mail.sh 75 %u
quota_warning2 = storage=90%% /opt/mail.sh 90 %u
}
Notice the only thing changed is the first variable: “quota”.
Also, if you want to use LDAP attributes to change your users’ quotas on a per-user basis, you need to do the following:
1) Rename your dovecot-ldap.conf file to dovecot-passdb-ldap.conf :
mv /etc/dovecot/dovecot-ldap.conf /etc/dovecot/dovecot-passdb-ldap.conf
2) Create a symlink to dovecot-passdb-ldap.conf called dovecot-userdb-ldap.conf :
ln -s /etc/dovecot/dovecot-passdb-ldap.conf /etc/dovecot/dovecot-userdb-ldap.conf
3) Modify your dovecot.conf file to point to these files as DBs for users and passwords:
passdb ldap {
args = /etc/dovecot/dovecot-passdb-ldap.conf
}
userdb ldap {
args = /etc/dovecot/dovecot-userdb-ldap.conf
}
4) And finally make sure your ” /etc/dovecot/dovecot-passdb-ldap.conf ” file looks like this:
hosts =
dn =
dnpass =
auth_bind = yes
ldap_version = 3
base = dc=example, dc=org
pass_filter = (&(objectClass=person)(userPrincipalName=%u))
user_filter = (&(objectClass=person)(userPrincipalName=%u))
user_attrs = otherPager=quota_rule=*:bytes=%$, userPrincipalName=home=/opt/data/mailboxes/%u
Notice we use the ” userPrincipalName ” as the attribute for username in dovecot (the username the users will also use to authenticate to dovecot). If you want, you can change this to whatever you want, like sAMAccountName.
Also, if you look carefully, notice that we used the ” otherPager ” attribute from LDAP as the attribute for user quota. We just modify this attribute for whatever we want to override the default quota for a certain user. For example we want to modify for user jon.doe, we just put in that attribute: ” 2G ” and the user will have 2 gigabytes. You can use any existing attribute that is not used and will not be or you can add your own to all the users in the LDAP tree.
That’s it! Restart Dovecot and it should work!
Recently we have bought a new server to replace an old HP DL360 that failed. The decision was made to buy a new Dell R410. This server, like many Dell servers, comes with a Broadcom dual-port Ethernet card. We wanted to install Debian Lenny (5.0) on it and this should have worked just fine with the bnx2 drivers that come with the latest Debian. But this particular ethernet card, Broadcom 5716, doesn’t work with them!
So we had to get the latest drivers for it! But because Broadcom doesn’t play nice with open-source, you have to get their latest drivers in binary form or compile them yourself from source. Because the compiling using their tarball failed for unknown reason and I didn’t have time to debug it, I searched for a precompiled Debian package (.deb). And it seems the deb from Debian’s Squeeze repository has the drivers that work with this particular card. So I downloaded and installed the package:
wget http://ftp.ro.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2_0.18_all.deb
dpkg -i firmware-bnx2_0.18_all.deb
Rebooted the machine but still no ethernet drivers. More searching lead me to find out that this firmware works with Linux kernel 2.6.30. Upgraded to this kernel (using debs also), rebooted and … network connectivity! But my joy quickly ended when I noticed on Openvz’s wiki that they only offer Openvz patches up to 2.6.27! So I had network but no way to use virtual machines with Openvz on it. (and this is what we use in our shop so no other options…).
But with Google’s help again, I noticed that Broadcom 5716 is supported in 2.6.27! No pre-compiled deb packages for this version, but no problem, we can compile our own. These are the steps to compile 2.6.27 with Openvz support and install the Broadcom latest drivers and make them work:
cd /usr/src
wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2
tar xjf linux-2.6.27.tar.bz2
cd linux-2.6.27
wget http://download.openvz.org/kernel/branches/2.6.27/2.6.27-briullov.1/patches/patch-briullov.1-combined.gz
(or whatever is the latest kernel patch for your kernel)
gunzip patch-briullov.1-combined.gz
wget http://download.openvz.org/kernel/branches/2.6.27/2.6.27-briullov.1/configs/kernel-2.6.27-x86_64.config.ovz
OR
wget http://download.openvz.org/kernel/branches/2.6.27/2.6.27-briullov.1/configs/kernel-2.6.27-i686.config.ovz
(depends on what platform your machine runs 32bit or 64bit)
cp kernel-2.6.27-*.config.ovz .config
patch -p1 < patch-briullov.1-combined
make oldconfig
make
make modules_install
make install
cd /boot
mkinitramfs -o initrd.img-2.6.27.21
update-grub
Edit /boot/grub/menu.lst and make the kernel 2.6.27.21 the default one.
wget http://ftp.ro.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2_0.18_all.deb
dpkg -i firmware-bnx2_0.18_all.deb
( in case you didn’t download and install the firmware earlier )
update-initramfs -u -t -k 2.6.27.21
apt-get install vzctl vzquota rsync
reboot
When you reboot in your system again, networking should work just fine along with Openvz!
Configuring a Samba server to use AD (LDAP) authentication can be a little tricky, especially because of the the little PAM tricks you need to do. I have searched a lot for info and tutorials, each giving you a little bit of the picture, and tested them until I came to a solution. I hope to spare you some of the work of digging and testing ;) Here goes!
This how-to is tested and works on a Debian system (4.0 / 5.0) using Samba version 3.2.5. It should work on other distros with minimum modifications but I do not guarantee it. Also, this is a copy / paste how-to, although I provided some small explanations at the end. You just need to modify generic info like “YOUR.DOMAIN” to your systems specific details.
Installing the packages
First we are going to install the needed packages:
” sudo apt-get install samba samba-common libkrb53 libpam-krb5 krb5-config krb5-user winbind “
Configuring nsswitch
Edit the file /etc/nsswitch.conf in order to have the following contents:
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference’ and `info’ packages installed, try:
# `info libc “Name Service Switch”‘ for information about this file.
# The next 3 lines are modified for winbind password checking before *nix password checking
passwd: winbind compat
group: winbind compat
shadow: winbind compat
hosts: files dns wins
networks: files dns
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
Configuring Kerberos5:
Now you need to edit the file /etc/krb5.conf to have the following contents:
[libdefaults]
default_realm = YOUR.DOMAIN
forwardable = true
ticket_lifetime = 24000
dns_lookup_kdc = false
dns_lookup_realm = false
[realms]
YOUR.DOMAIN = {
kdc = your.AD.server
admin_server = your.AD.server
default_domain = YOUR.DOMAIN
}
[domain_realm]
.your.domain = YOUR.DOMAIN
your.domain = YOUR.DOMAIN
[login]
krb4_convert = true
krb4_get_tickets = false
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[appdefaults]
pam = {
debug = false
ticket_lifetime = 36000
renew_lifetime = 36000
forwardable = true
krb4_convert = false
}
Configuring PAM
The next step is to configure PAM to first try to use Winbind authentication instead of local *nix style authenticaion. This will NOT mess with your local authentication for terminal or SSH access.
First file we need to edit is /etc/pam.d/common-account :
#
# /etc/pam.d/common-account – authorization settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authorization modules that define
# the central access policy for use on the system. The default is to
# only deny service to users whose accounts are expired in /etc/shadow.
#
# PAM Winbind plugin before *nix accounting
account sufficient pam_winbind.so
account required pam_unix.so
Next one is /etc/pam.d/common-auth :
# /etc/pam.d/common-auth – authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
# PAM winbind plugin before *nix authentication
auth required /lib/security/pam_securetty.so
auth sufficient /lib/security/pam_winbind.so
auth sufficient /lib/security/pam_unix.so use_first_pass
auth required /lib/security/pam_nologin.so
And the last one is /etc/pam.d/common-password :
# /etc/pam.d/common-password – password-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of modules that define the services to be
#used to change user passwords. The default is pam_unix
# The “nullok” option allows users to change an empty password, else
# empty passwords are treated as locked accounts.
#
# (Add `md5′ after the module name to enable MD5 passwords)
#
# The “obscure” option replaces the old `OBSCURE_CHECKS_ENAB’ option in
# login.defs. Also the “min” and “max” options enforce the length of the
# new password.
password sufficient pam_winbind.so
password sufficient pam_unix.so nullok obscure md5
Configuring Samba and the shares
First create the directories that you will use for the shares. In this example we will use /opt/data/samba in which we will make 2 other directories: public and restricted.
Now edit the file /etc/samba/smb.conf :
[global]
debug level = 3
kernel oplocks = no
realm = YOUR.DOMAIN
workgroup = DOMAIN ### domain name without the TLD – .com for example ###
netbios name = <A name by which the server will be seen in the network>
server string = File Server
load printers = no
log file = /var/log/samba/debug.log
max log size = 50
local master = no
domain master = no
preferred master = no
security = ADS
password server = your.AD.server
encrypt passwords = yes
socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
wins proxy = no
dns proxy = no
winbind enum users = yes
winbind enum groups = yes
winbind use default domain = yes
winbind separator = +
winbind refresh tickets = yes
idmap uid = 10000-20000
idmap gid = 10000-20000
[public]
path = /opt/data/samba/public
comment = Public access folder
read only = no
force user = %U
force group = “DOMAIN+domain users”
force create mode = 0666
force directory mode = 2777
force directory security mode = 0777
valid users = @”DOMAIN+domain users”
[restricted]
path = /opt/data/samba/it
comment = Restricted access folder
writable = yes
force user = %U
force group = “DOMAIN+<AD group that is allowed to access>”
force create mode = 0660
create mask = 0660
force directory mode = 0770
force directory security mode = 0770
valid users = @”DOMAIN+<AD group that is allowed to access>”
I will explain some of the configuration directives used here for smb.conf. The first two are:
security = ADS
password server = your.AD.server
This will tell Samba to use Active Directory security and that the server Samba needs to verify the passwords against is the local domain controller (the one that holds the AD tree).
The next two are:
winbind use default domain = yes
winbind separator = +
If the first directive is set to “yes”, you won’t need to use the domain also when setting file permissions. Samba / Winbind will know to use what you have set in the “realm” directive in front of every group / user used for authentication or authorization. The second one just tells Samba what to use as separator between the “realm” and user or group.
This directive:
winbind refresh tickets = yes
will tell Samba to refresh the kerberos tickets after joining the domain, as not to “unjoin” it and become unable to authenticate against the AD.
As for the shares, you can use the variable “%U” as the authenticated user to force the ownership or to grant access. Also, you can use groups in the AD to allow access using the directive “valid users =” followed by the name of the group with the domain in front.
Example: valid users = @”DOMAIN+restricted-access-group” . Please use the separator that you have set above with “winbind separator”
The rest of the directives are usual Samba directives.
Now restart Samba and Winbind:
” sudo /etc/init.d/samba restart ”
” sudo /etc/init.d/winbind restart ”
Joining the domain
For Samba to be able the verify usernames and passwords against the Active Directory, the server must first be joined in the domain. To do that we need to use the “net ads join” command:
” net ads join -S your.AD.server -U user%password “
The user and password must be valid a valid user in the domain that has the permission to join it.
To verify that the server has joined the domain you can use the following commands:
” net ads status -S your.AD.server -U user%password “
or
” net ads info “
Also, to be safe run the following commands:
” wbinfo -u “
” wbinfo -g “
The first one should list all the domain users and the second one the domain groups. If this is so and you have seen the user and group list that means that the server is joined and is able to see verify the usernames / passwords.
Setting file permissions
Now that Samba is configured and the server joined the domain, the last thing to do is to set the Unix style file permissions on the share folders. But now, you can use the users and groups in the domain as the owner and group settings of the folders and files. For example:
” chown “jon.doe” /opt/data/samba/restricted -R “
” chgrp “restricted-access-group” /opt/data/samba/restricted -R “
” chmod g+rw /opt/data/samba/restricted -R “
or to make all the users in the domain able to read and write the public folder:
” chgrp “domain users” /opt/data/samba/public -R “
” chmod g+rw /opt/data/samba/public -R “
That’s it! Now you should be able to access Samba shares using your AD username and password!