Random wallpapers

If you ever want to randomly change your wallpapers every few minutes, hours or whatever, I just made a script to do just that. You can find it here.

This script will at regular interval select a random file within the specified directory and use the specified command to use it as a wallpaper. For example if you want to change your wallpaper every 10 minutes with a picture in ~/Pictures/wallpapers.

wp-random.sh 600 ~/Pictures/wallpapers/ feh --bg-scale

Note that we use feh here to setup the wallpaper, but you can use any command you like.

You can use SIGUSR1 to redraw the current wallpaper (for example if you just enabled the VGA output and the background needs a redraw), or SIGUSR2 to force the selection of another wallpaper:


WP_RANDOM_PID=$(cat /tmp/wp-random_$DISPLAY.pid)

# Redraw current wallpaper
kill -SIGUSR1 "$WP_RANDOM_PID"

# Select another wallpaper
kill -SIGUSR2 "$WP_RANDOM_PID"

IPs ban on Linux

Ban Hammer

Who needs a quick ban?

Today we had a bruteforce attack on our nginx server. Well cannot say he was anywhere near successful though, the guy did POST /wp-login.php several times per second and all he got as an answer was 404. Fat chance…

But still, he had our access logs growing far larger than they usually do. So I tried to ban him. Unfortunately nginx does not use TCP wrappers by default (you can use ngx_tcpwrappers although it will have to be rebuilt from source).

So I made a little script, called ban-hammer to temporarily ban IPs using IPTables. There is also a cron.daily script to unban IPs each day. The script requires rpnc, but it is easy to adapt without it.

These scripts add and remove the IPs into a special IPT chain (which you can configure in the script). So you also have to configure your firewall to jump to the two chains and load banned IPs on boot:

echo "Bans"

load_bans() {
  ban_table=$1
  ban_chain=$2
  iptables=$3

  $iptables -N $ban_chain

  while read ban
  do
    ip=$(echo "$ban" | cut -d'=' -f 1)
    $iptables -A $ban_chain -s "$ip" -j DROP
  done < "$ban_table"

  $iptables -A INPUT -j $ban_chain
}

load_bans /etc/firewall/ip4.ban IP4BAN iptables
load_bans /etc/firewall/ip6.ban IP6BAN ip6tables

Get rid of SIGINT

Yesterday I had some problems trying to get rid of the SIGINT signal (when you press C-c on your terminal). Imagine you have the following script :

# a.sh

b &
sleep

Let’s suppose that b is a sleep or another simple command or a shell script. In that case a SIGINT on the terminal will kill a.sh but b will be rattached to init. This is strange because:

  1. b effectively receives the signal (seen with strace)
  2. the default action should terminate the process
The reason behind this is that the shell will (roughly) do the following sequence of operations before starting the process in the background:
if(!fork()) {
  /* child */
  signal(SIGINT, SIG_IGN);
  signal(SIGQUIT, SIG_IGN);

  execve(...cmd...);
}

 

The execve manpage has this to say about signals:

*  POSIX.1-2001 specifies that the dispositions of any signals that are
ignored or set to the default are  left  unchanged.

i.e. the process will inherit SIG_IGN signals and set all the others to default. So with our shell the SIGINT is ignored for the background processes. However if the process defines its own handler and catch the signal, it will override the inherited SIG_IGN value. This is the case for example with tcpdump which will catch this signal to terminate properly. This is also the case for the following code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

void sigint(int n)
{
  printf("child int; exitn");
  exit(0);
}

int main()
{
  signal(SIGINT, sigint);
  usleep(-1);
}

In this case the process will catch SIGINT and terminate. So if we cannot prevent the process to catch the signal the question now is: How can we prevent b to receive the signal?

When this signal is generated, it is sent to the foreground process group on the session associated to the tty. If you have a shell open on your tty, it will be the currently running command if any. In this case the current command is a non-interactive shell script. In this non-interactive shell, all commands even those sent to background with “&” are attached to the same process group. So here the background commands of the shell script are associated to the foreground process group.  This is why they still receive SIGINT even when the parent process die and they are rattached to init.

The solution is to create the processes which we want to make unaware of SIGINT in a new process group, different from the foreground process group and therefore a background process group. However there is no command to start something in a new process group. Instead we have a command which can start something in a new session and therefore a new process group too. Better still, your process is detached from your tty which makes it (nearly) a real daemon. So the solution is:

# a.sh

setsid b &
sleep

Another solution forces the shell to turn on job control in non-interactive mode with set -m. This way each background process will be created in a new process group. This could be embarrassing though because you cannot background processes in the same process group anymore. Basically we want processes in the same process group to make sure that a SIGINT will terminate the entire script, background commands included. Otherwise you have to save the pid, trap the SIGINT signal and take care of terminating everything by yourself.

Moreover using setsid is a part of the REAL answer to this question:

“How do we fully detach a process from its tty?”

For which we almost see:

“Use nohup…”

Which is wrong! According to man nohup justs: “run a command immune to hangups, with output to a non-tty”. That is, it will just adjust input/output, ignore SIGHUP and exec your command. However if you do something like signal(SIGHUP, SIG_DFL); then nohup has no effect anymore and the process will be terminated when the terminal hang up.

Attach a patch to an issue on GitHub

You can’t attach a patch on an issue on GitHub. Instead, it seems you have to use this :

https://gist.github.com

Well… Copy-pasting ain’t a way to issue a patch. So I made a little script to upload files on my server. You can download it here:

https://raw.github.com/gawen947/scripts/master/bin/upload.sh

It uses some other commands from the SUnix repository. Though it should be easy to adapt it without them.

http://github.com/gawen947/sunix