Sonntag, 23. November 2014

Limit the number of simultaneous SSH connections

Brute-force attacks on user passwords via SSH work, because SSH does not limit the number of simultaneous connections. If you use SSH and Screen to manage your host, you will most likely never need more than three connections.

  1. A connections for the Screen session.
  2. A connections to transfer files with SCP.
  3. And a spare connection, if your Screen connection hangs or you need another simultaneous file transfer.

This means that it is sufficient to allow three TCP SYN packets on port 22. The following command inserts the appropriate rule at the beginning of the Netfilter INPUT chain.

iptables -I INPUT 1 -p tcp --syn --dport 22 \
         -m connlimit --connlimit-above 3 --connlimit-mask 32 \
         -j DROP

Just another abuse joke

Yesterday my server was under attack by the following addresses.

  • 62.210.141.172
  • 62.210.172.143
  • 62.210.172.206

A revers lookup of the addresses shows that they belong to poneytelecom.eu.

# for addr in 62.210.141.172 62.210.172.143 62.210.172.206; do dig -x $addr +short; done
62-210-141-172.rev.poneytelecom.eu.
62-210-172-143.rev.poneytelecom.eu.
62-210-172-206.rev.poneytelecom.eu.

Taking a look at the web page reveals an abuse link. I was impressed and gave it a try. I entered the IP addresses and the correct time. Next I entered my e-mail address the abuse type "Bruteforce" and pasted a copy of my ssh authentication log.

auth.info: Nov 22 17:04:22 sshd[2199]: Failed password for root from 62.210.172.206 port 50916 ssh2
auth.info: Nov 22 17:04:28 sshd[2199]: Failed password for root from 62.210.172.206 port 50916 ssh2
auth.info: Nov 22 17:04:33 sshd[2199]: Failed password for root from 62.210.172.206 port 50916 ssh2
auth.info: Nov 22 17:04:43 sshd[2218]: Failed password for root from 62.210.172.206 port 55633 ssh2
auth.info: Nov 22 17:04:50 sshd[2218]: Failed password for root from 62.210.172.206 port 55633 ssh2
auth.info: Nov 22 17:04:57 sshd[2218]: Failed password for root from 62.210.172.206 port 55633 ssh2
auth.info: Nov 22 17:05:07 sshd[2251]: Failed password for root from 62.210.172.206 port 60456 ssh2
auth.info: Nov 22 17:05:14 sshd[2251]: Failed password for root from 62.210.172.206 port 60456 ssh2
auth.info: Nov 22 17:05:20 sshd[2251]: Failed password for root from 62.210.172.206 port 60456 ssh2
auth.info: Nov 22 17:05:31 sshd[2271]: Failed password for root from 62.210.172.206 port 35897 ssh2
auth.info: Nov 22 17:05:38 sshd[2271]: Failed password for root from 62.210.172.206 port 35897 ssh2
auth.info: Nov 22 17:05:44 sshd[2271]: Failed password for root from 62.210.172.206 port 35897 ssh2
auth.info: Nov 22 17:05:52 sshd[2293]: Failed password for root from 62.210.172.206 port 39627 ssh2
auth.info: Nov 22 17:05:58 sshd[2293]: Failed password for root from 62.210.172.206 port 39627 ssh2
auth.info: Nov 22 17:06:02 sshd[2293]: Failed password for root from 62.210.172.206 port 39627 ssh2
auth.info: Nov 22 17:06:10 sshd[2315]: Failed password for root from 62.210.172.206 port 42566 ssh2
auth.info: Nov 22 17:06:16 sshd[2315]: Failed password for root from 62.210.172.206 port 42566 ssh2
auth.info: Nov 22 17:06:22 sshd[2315]: Failed password for root from 62.210.172.206 port 42566 ssh2
auth.info: Nov 22 17:06:30 sshd[2337]: Failed password for root from 62.210.172.206 port 55252 ssh2
auth.info: Nov 22 17:06:34 sshd[2337]: Failed password for root from 62.210.172.206 port 55252 ssh2
auth.info: Nov 22 17:06:38 sshd[2337]: Failed password for root from 62.210.172.206 port 55252 ssh2
auth.info: Nov 22 17:06:48 sshd[2354]: Failed password for root from 62.210.172.206 port 38336 ssh2
auth.info: Nov 22 17:06:55 sshd[2354]: Failed password for root from 62.210.172.206 port 38336 ssh2
auth.info: Nov 22 17:07:01 sshd[2354]: Failed password for root from 62.210.172.206 port 38336 ssh2
auth.info: Nov 22 17:07:11 sshd[2374]: Failed password for root from 62.210.172.206 port 53116 ssh2
auth.info: Nov 22 17:07:18 sshd[2374]: Failed password for root from 62.210.172.206 port 53116 ssh2
auth.info: Nov 22 17:07:24 sshd[2374]: Failed password for root from 62.210.172.206 port 53116 ssh2
auth.info: Nov 22 17:07:34 sshd[2397]: Failed password for root from 62.210.172.206 port 40920 ssh2
auth.info: Nov 22 17:07:40 sshd[2397]: Failed password for root from 62.210.172.206 port 40920 ssh2
auth.info: Nov 22 17:07:46 sshd[2397]: Failed password for root from 62.210.172.206 port 40920 ssh2
auth.info: Nov 22 17:07:56 sshd[2421]: Failed password for root from 62.210.172.206 port 55725 ssh2
auth.info: Nov 22 17:08:06 sshd[2421]: Failed password for root from 62.210.172.206 port 55725 ssh2
auth.info: Nov 22 17:08:12 sshd[2421]: Failed password for root from 62.210.172.206 port 55725 ssh2
auth.info: Nov 22 17:08:23 sshd[2444]: Failed password for root from 62.210.172.206 port 52929 ssh2
auth.info: Nov 22 17:08:29 sshd[2444]: Failed password for root from 62.210.172.206 port 52929 ssh2
auth.info: Nov 22 17:08:36 sshd[2444]: Failed password for root from 62.210.172.206 port 52929 ssh2
auth.info: Nov 22 17:08:47 sshd[2464]: Failed password for root from 62.210.172.206 port 48487 ssh2
auth.info: Nov 22 17:08:53 sshd[2464]: Failed password for root from 62.210.172.206 port 48487 ssh2
auth.info: Nov 22 17:08:59 sshd[2464]: Failed password for root from 62.210.172.206 port 48487 ssh2
auth.info: Nov 22 17:09:11 sshd[2494]: Failed password for root from 62.210.172.206 port 41285 ssh2
auth.info: Nov 22 17:09:16 sshd[2494]: Failed password for root from 62.210.172.206 port 41285 ssh2
auth.info: Nov 22 17:09:21 sshd[2494]: Failed password for root from 62.210.172.206 port 41285 ssh2
auth.info: Nov 22 17:09:32 sshd[2516]: Failed password for root from 62.210.172.206 port 34060 ssh2
auth.info: Nov 22 17:09:37 sshd[2516]: Failed password for root from 62.210.172.206 port 34060 ssh2
auth.info: Nov 22 17:09:43 sshd[2516]: Failed password for root from 62.210.172.206 port 34060 ssh2
auth.info: Nov 22 17:09:51 sshd[2537]: Failed password for root from 62.210.172.206 port 52864 ssh2
auth.info: Nov 22 17:09:56 sshd[2537]: Failed password for root from 62.210.172.206 port 52864 ssh2
auth.info: Nov 22 17:10:02 sshd[2537]: Failed password for root from 62.210.172.206 port 52864 ssh2
auth.info: Nov 22 17:10:13 sshd[2565]: Failed password for root from 62.210.172.206 port 41045 ssh2
auth.info: Nov 22 17:10:19 sshd[2565]: Failed password for root from 62.210.172.206 port 41045 ssh2
auth.info: Nov 22 17:10:24 sshd[2565]: Failed password for root from 62.210.172.206 port 41045 ssh2
auth.info: Nov 22 17:10:35 sshd[2593]: Failed password for root from 62.210.172.206 port 35403 ssh2
auth.info: Nov 22 17:10:41 sshd[2593]: Failed password for root from 62.210.172.206 port 35403 ssh2
auth.info: Nov 22 17:10:47 sshd[2593]: Failed password for root from 62.210.172.206 port 35403 ssh2
auth.info: Nov 22 17:10:58 sshd[2615]: Failed password for root from 62.210.172.206 port 37722 ssh2
auth.info: Nov 22 17:11:04 sshd[2615]: Failed password for root from 62.210.172.206 port 37722 ssh2
auth.info: Nov 22 17:11:11 sshd[2615]: Failed password for root from 62.210.172.206 port 37722 ssh2
auth.info: Nov 22 17:11:22 sshd[2638]: Failed password for root from 62.210.172.206 port 53056 ssh2
auth.info: Nov 22 17:11:28 sshd[2638]: Failed password for root from 62.210.172.206 port 53056 ssh2
auth.info: Nov 22 17:11:35 sshd[2638]: Failed password for root from 62.210.172.206 port 53056 ssh2
auth.info: Nov 22 17:11:46 sshd[2660]: Failed password for root from 62.210.172.206 port 43890 ssh2
auth.info: Nov 22 17:12:22 sshd[2688]: Failed password for root from 62.210.172.206 port 58024 ssh2
auth.info: Nov 22 17:12:27 sshd[2688]: Failed password for root from 62.210.172.206 port 58024 ssh2
auth.info: Nov 22 17:12:32 sshd[2688]: Failed password for root from 62.210.172.206 port 58024 ssh2
auth.info: Nov 22 17:12:39 sshd[2702]: Failed password for root from 62.210.172.206 port 34130 ssh2
auth.info: Nov 22 17:12:44 sshd[2702]: Failed password for root from 62.210.172.206 port 34130 ssh2
auth.info: Nov 22 17:12:48 sshd[2702]: Failed password for root from 62.210.172.206 port 34130 ssh2
auth.info: Nov 22 17:12:57 sshd[2718]: Failed password for root from 62.210.172.206 port 40606 ssh2
auth.info: Nov 22 17:13:04 sshd[2718]: Failed password for root from 62.210.172.206 port 40606 ssh2
auth.info: Nov 22 17:13:11 sshd[2718]: Failed password for root from 62.210.172.206 port 40606 ssh2
auth.info: Nov 22 17:13:21 sshd[2788]: Failed password for root from 62.210.172.206 port 48292 ssh2
auth.info: Nov 22 17:13:26 sshd[2788]: Failed password for root from 62.210.172.206 port 48292 ssh2
auth.info: Nov 22 17:13:31 sshd[2788]: Failed password for root from 62.210.172.206 port 48292 ssh2
auth.info: Nov 22 17:13:41 sshd[2814]: Failed password for root from 62.210.172.206 port 43521 ssh2
auth.info: Nov 22 17:13:47 sshd[2814]: Failed password for root from 62.210.172.206 port 43521 ssh2
auth.info: Nov 22 17:13:52 sshd[2814]: Failed password for root from 62.210.172.206 port 43521 ssh2
auth.info: Nov 22 17:14:02 sshd[2834]: Failed password for root from 62.210.172.206 port 43164 ssh2
auth.info: Nov 22 17:14:07 sshd[2834]: Failed password for root from 62.210.172.206 port 43164 ssh2
auth.info: Nov 22 17:14:13 sshd[2834]: Failed password for root from 62.210.172.206 port 43164 ssh2
auth.info: Nov 22 17:14:22 sshd[2854]: Failed password for root from 62.210.172.206 port 37908 ssh2
auth.info: Nov 22 17:14:27 sshd[2854]: Failed password for root from 62.210.172.206 port 37908 ssh2
auth.info: Nov 22 17:14:32 sshd[2854]: Failed password for root from 62.210.172.206 port 37908 ssh2
auth.info: Nov 22 17:14:42 sshd[2874]: Failed password for root from 62.210.172.206 port 56492 ssh2
auth.info: Nov 22 17:14:44 sshd[2874]: Failed password for root from 62.210.172.206 port 56492 ssh2
auth.info: Nov 22 17:14:50 sshd[2874]: Failed password for root from 62.210.172.206 port 56492 ssh2
auth.info: Nov 22 17:15:00 sshd[2889]: Failed password for root from 62.210.172.206 port 41655 ssh2
auth.info: Nov 22 17:15:05 sshd[2889]: Failed password for root from 62.210.172.206 port 41655 ssh2
auth.info: Nov 22 17:15:10 sshd[2889]: Failed password for root from 62.210.172.206 port 41655 ssh2
auth.info: Nov 22 17:15:21 sshd[2910]: Failed password for root from 62.210.172.206 port 34993 ssh2
auth.info: Nov 22 17:15:26 sshd[2910]: Failed password for root from 62.210.172.206 port 34993 ssh2
auth.info: Nov 22 17:15:32 sshd[2910]: Failed password for root from 62.210.172.206 port 34993 ssh2
auth.info: Nov 22 17:15:41 sshd[2933]: Failed password for root from 62.210.172.206 port 52663 ssh2
auth.info: Nov 22 17:15:44 sshd[2933]: Failed password for root from 62.210.172.206 port 52663 ssh2
auth.info: Nov 22 17:15:50 sshd[2933]: Failed password for root from 62.210.172.206 port 52663 ssh2
auth.info: Nov 22 17:15:58 sshd[2951]: Failed password for root from 62.210.172.206 port 35746 ssh2
auth.info: Nov 22 17:16:04 sshd[2951]: Failed password for root from 62.210.172.206 port 35746 ssh2
auth.info: Nov 22 17:16:11 sshd[2951]: Failed password for root from 62.210.172.206 port 35746 ssh2
auth.info: Nov 22 17:16:19 sshd[2973]: Failed password for root from 62.210.172.206 port 57551 ssh2
auth.info: Nov 22 17:16:25 sshd[2973]: Failed password for root from 62.210.172.206 port 57551 ssh2
auth.info: Nov 22 17:16:29 sshd[2973]: Failed password for root from 62.210.172.206 port 57551 ssh2
auth.info: Nov 22 17:16:37 sshd[2993]: Failed password for root from 62.210.172.206 port 40210 ssh2
auth.info: Nov 22 17:16:41 sshd[2993]: Failed password for root from 62.210.172.206 port 40210 ssh2
auth.info: Nov 22 17:16:47 sshd[2993]: Failed password for root from 62.210.172.206 port 40210 ssh2
auth.info: Nov 22 17:16:54 sshd[3019]: Failed password for root from 62.210.172.206 port 53521 ssh2
auth.info: Nov 22 17:16:59 sshd[3019]: Failed password for root from 62.210.172.206 port 53521 ssh2
auth.info: Nov 22 17:17:04 sshd[3019]: Failed password for root from 62.210.172.206 port 53521 ssh2
auth.info: Nov 22 17:17:11 sshd[3043]: Failed password for root from 62.210.172.206 port 33313 ssh2
auth.info: Nov 22 17:17:14 sshd[3043]: Failed password for root from 62.210.172.206 port 33313 ssh2
auth.info: Nov 22 17:17:19 sshd[3043]: Failed password for root from 62.210.172.206 port 33313 ssh2
auth.info: Nov 22 17:17:28 sshd[3062]: Failed password for root from 62.210.172.206 port 60962 ssh2
auth.info: Nov 22 17:17:33 sshd[3062]: Failed password for root from 62.210.172.206 port 60962 ssh2
auth.info: Nov 22 17:17:37 sshd[3062]: Failed password for root from 62.210.172.206 port 60962 ssh2
auth.info: Nov 22 17:17:45 sshd[3078]: Failed password for root from 62.210.172.206 port 43115 ssh2
auth.info: Nov 22 17:17:52 sshd[3078]: Failed password for root from 62.210.172.206 port 43115 ssh2
auth.info: Nov 22 17:17:58 sshd[3078]: Failed password for root from 62.210.172.206 port 43115 ssh2
auth.info: Nov 22 17:18:05 sshd[3096]: Failed password for root from 62.210.172.206 port 55068 ssh2
auth.info: Nov 22 17:18:09 sshd[3096]: Failed password for root from 62.210.172.206 port 55068 ssh2
auth.info: Nov 22 17:18:14 sshd[3096]: Failed password for root from 62.210.172.206 port 55068 ssh2
auth.info: Nov 22 17:18:20 sshd[3114]: Failed password for root from 62.210.172.206 port 59523 ssh2
auth.info: Nov 22 17:18:26 sshd[3114]: Failed password for root from 62.210.172.206 port 59523 ssh2
auth.info: Nov 22 17:18:32 sshd[3114]: Failed password for root from 62.210.172.206 port 59523 ssh2
auth.info: Nov 22 17:18:40 sshd[3130]: Failed password for root from 62.210.172.206 port 41482 ssh2
auth.info: Nov 22 17:18:46 sshd[3130]: Failed password for root from 62.210.172.206 port 41482 ssh2
auth.info: Nov 22 17:18:52 sshd[3130]: Failed password for root from 62.210.172.206 port 41482 ssh2
auth.info: Nov 22 17:19:01 sshd[3148]: Failed password for root from 62.210.172.206 port 59707 ssh2
auth.info: Nov 22 17:19:04 sshd[3148]: Failed password for root from 62.210.172.206 port 59707 ssh2
auth.info: Nov 22 17:19:08 sshd[3148]: Failed password for root from 62.210.172.206 port 59707 ssh2
auth.info: Nov 22 17:19:14 sshd[3165]: Failed password for root from 62.210.172.206 port 33131 ssh2
auth.info: Nov 22 17:19:18 sshd[3165]: Failed password for root from 62.210.172.206 port 33131 ssh2
auth.info: Nov 22 17:19:21 sshd[3165]: Failed password for root from 62.210.172.206 port 33131 ssh2
auth.info: Nov 22 17:19:26 sshd[3177]: Failed password for root from 62.210.172.206 port 53828 ssh2
auth.info: Nov 22 17:19:30 sshd[3177]: Failed password for root from 62.210.172.206 port 53828 ssh2
auth.info: Nov 22 17:19:33 sshd[3177]: Failed password for root from 62.210.172.206 port 53828 ssh2
auth.info: Nov 22 17:19:36 sshd[3186]: Failed password for root from 62.210.172.206 port 40026 ssh2
auth.info: Nov 22 17:19:39 sshd[3186]: Failed password for root from 62.210.172.206 port 40026 ssh2
auth.info: Nov 22 17:19:41 sshd[3186]: Failed password for root from 62.210.172.206 port 40026 ssh2

I did the same for the two other attacking addresses.

Next I got thre e-mails from noreply@online.net which tell me that I should confirm the abuse report. I did so and thought nice, it seems to work.

[Online] Abuse #38682 - mail confirmation for abuse on server ip address 62.210.172.206

ONLINE SAS
Technical assistance
BP 438 - 75366 Paris CEDEX 08
France

Tel: +33 1 84 13 00 00
Fax: +33 899 173 788 (1.35 EUR / call then 0.34 EUR / min from a French landline)

Subject : Abuse request

Dear Sir or Madam,

Thank you for your abuse request on server ip address 62.210.172.206.

We have record it with reference A-38682.

Please confirm your abuse using this address:

https://console.online.net/en/account/abuses/confirm/38682/1416672261/a70bdf4c27fff2db6e16bf0a67ed4aa2

You will receive an answer from our customer or our abuse service in 24 to 48 hours delay after confirmation.

If you have any questions, please contact our assistance https://console.online.net/assistance/

Best regards,

--
The Online team

Fine so far, I thought.

But this morning I had a choking cough, because I made to mistake to check my e-mail while eating a bun. I got three masterpiece of incident resolution intelligence. This is one of them.

[Online] Abuse #38682 - abuse for server ip address 62.210.172.206 resolved

ONLINE SAS
Technical assistance
BP 438 - 75366 Paris CEDEX 08
France

Tel: +33 1 84 13 00 00
Fax: +33 899 173 788 (1.35 EUR / call then 0.34 EUR / min from a French landline)

Subject : Abuse notification resolved

Dear Sir or Madam,

Your abuse number 38682 is now closed.

Here is a comment left by our customer:
----------------------------------------------------------------

Why root account password will change by oneself?

----------------------------------------------------------------

If you have any questions, please contact our assistance https://console.online.net/assistance/

Best regards,

--
The Online team

All the effort to implement a nice abuse workflow is rendered superfluous by a stupid bone-head user accepting a useless counter question having nothing to do with the attack and explaining even less.

Samstag, 22. November 2014

Ban assholes trying to hack SSH passwords.

Normally I do not care much about those assholes trying to hack my system by probing SSH passwords. But today a probing attack took so much resources, that my own session starts lagging. So I had to take a fly swap to smash the gadfly. Here is the swap.

#! /bin/bash
##
## Ban SSH password cracking attempts.
##
## Time-stamp: <2014-11-22 19:26:44 szi>
##

set -eu

FILE="$1"; shift

IP='[0-9]\+\.[0-9]\+\.[0-9]\+.[0-9]\+'
TZ=$(date '+%Y-%m-%d %H:%M:%S %z')

# Search failed SSH logins.
sed -n 's/.* sshd\[[0-9]*\]: Failed password .* \('"$IP"'\).*/\1/p' "$FILE" |
# Count the number of failures.
sort | uniq -c |
# Select all addresses with more than 3 failures.
awk '$1>3 {print $2}' |
# Remove the already banned.
grep -v -f <(iptables -n -L INPUT | awk '$1=="DROP" {print $4}') |
# Report
tee >(read LINE < <(xargs echo); echo "Banning: ${LINE:-none}" >&2) |
# And ban the new assholes.
xargs -i iptables -A INPUT -s '{}' -m comment --comment "$TZ" -j DROP

The script needs the file containing the SSH auth log as an argument and can be run in a cron job every five minutes. Each drop rule gets a time stamp. This makes it possible to remove old entries, if the INPUT chain gets too big.

Here is an example. Flush the INPUT chain:

# iptables -F INPUT

Run the script:

# banip /var/log/auth.log
Banning: 103.41.124.12 122.225.109.211 122.225.97.75 122.225.97.97 222.186.34.119 61.136.171.198 62.210.141.172 62.210.172.143 62.210.172.206 82.165.128.189

Control the new input chain:

# iptables -n -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  103.41.124.12        0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  122.225.109.211      0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  122.225.97.75        0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  122.225.97.97        0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  222.186.34.119       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  61.136.171.198       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  62.210.141.172       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  62.210.172.143       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  62.210.172.206       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */
DROP       all  --  82.165.128.189       0.0.0.0/0            /* 2014-11-22 19:27:44 +0100 */

Of course it is also possible to install fail2ban but my small Geode has only 256MB RAM and therefor I have to minimize my services. The above script is enough for me.

The code can be found on Github.

Freitag, 21. November 2014

PwdHash on the command line

PwdHash is a way to generate different passwords for different sites based on the same master password. Many plugins and adoptions exist for different browsers and also implementations for Android. Apple sucks: there is no way to have browser plugins on an iPhone. Who cares for the dead?

But sometimes it is useful to be able to generate the password hashes on the command line without using a browser. This can be done with a JavaScript engine like SpiderMonkey. The following script shows how to fetch the JavaScript code from pwdhash.com for SpiderMonkey to generate a password.

#! /bin/bash

URL=$1; shift

read -s -p "Password: " PW
echo

get () { curl -sSL https://www.pwdhash.com/"$*"; }

scripts () { get | sed -n 's/.*script src="\(.*\).js".*/\1/p'; }

smjs <(
  for JS in $(scripts); do get "$JS".js; done
  echo "print(new String(new SPH_HashedPassword('$PW','$URL')));"
)

Of course it would be better to extract the script names with an XPath expression like /html/meta/script[@type="text/javascript"]/@src but unfortunately the HTML code of pwdhash.com is currently broken and can neither be parsed by xmllint nor by SaxonHE. Normally I would not suggest to use sed to parse HTML but in this case it seems to be simpler.

On Debian you need the packages curl and spidermonkey-bin.

apt-get install curl spidermonkey-bin libnspr4

Montag, 17. November 2014

Undelete für "rm *"

Verdammte Scheiße! Gerade ist es mir wieder passiert. Das letzte mal ist schon ein paar Jahre her. Und ich hätte nicht gedacht, dass es mir nochmal passiert. Aber im Eifer des Gefechts, wenn man nicht genau hinsieht und die Tab-Completion auf einer langsamen SSH-Leitung einem Dinge vorgaukelt, die nicht wirklich so sind wie sie scheinen, ja so ist es mir passiert. Und natürlich habe ich mir gespart die Arbeit der letzten paar Tage einzuchecken, will man ja immer erst machen, wenn es wirklich rund läuft. Scheiß drauf! In Zukunft wird jeder Müll eingecheckt. Aber das hilft jetzt leider nicht weiter.

Gelöschte Daten auf einem Linux-Dateisystem zu rekonstruieren ist nicht so einfach und wenn einem ein solches Malheur passiert ist, gilt es Ruhe zu bewahren. Jeder weitere Schreibzugriff auf die betreffende Platte kann dazu führen, dass die gelöschten Daten unwiederbringlich verloren sind. Natürlich kann man die Platte wegmounten und mit mit diversen Tools ein Backup machen, um darin noch was zu finden. Wenn man aber über SSH auf einem Produktionssystem ist, stellen solche Tools meist keine Option dar.

Was aber geht ist ein grep auf das Raw-Device. Und in meinem Fall hat genau das geholfen. Dazu muss man sich aber an den Anfang der Datei erinnern. Wenn man den noch kennt, kann man grep dazu überreden eine Binärdatei wie eine Textdatei zu behandeln. Mit den Optionen -B und -A kann man den Bereich vor und hinter der Überschrift eingrenzen und less zeigt die Daten an, ohne das Terminal zu schrotten.

grep --binary-files=text -B 1 -A 500 \
  '## Various Bash functions' \
  /dev/disk/by-uuid/6989be6b-e743-419a-bd8b-bc877756dfe2 |
less

Puh nochmal Glück gehabt:

Donnerstag, 13. November 2014

Apple 20 Jahre später und kein bischen besser

Ich bin jetzt leider dazu verdammt, ein Apple-Produkt zu benutzen. Seit 20 Jahren ist der Kelch zum Glück an mir vorüber gegangen aber jetzt gibt es in meiner Firma keine anderen Telefone mehr als solche von Apple. Der ersten Schock, an dessen Überwindung ich zur Zeit arbeite, hat mich direkt in die frühen 90er zurück katapultiert: das dumme iPhone hat keine Zurück-Taste. Schon damals hat Apple an den Tasten gespart und der Maus nur eine davon spendiert, während jede Workstation seit ewigen Zeiten drei Tasten hatte. Aber damals, anders als jetzt, war ich nicht dazu gezwungen, mit dem wenigen auskommen zu müssen, was Apple seinem typischerweise technisch beschränkten Klientel zuzumuten sich wagt.

Nachdem ich feststellen musste, dass auch die Musik noch die gleiche ist wie in den 90ern, konnte ich jedoch mit großem Erstaunen eine echte Veränderung beobachten: Mosaic heißt jetzt Safari. Von dem, was der neue iPhone-Browser kann, unterscheidet er sich allerdings wiederum kaum von dem aus den 90ern: Plugins gehen heute genauso wenig wie damals. Und damit wird es jetzt wirklich lästig. Denn anders als damals in den Anfängen des Internets, wo man private Vereine gründen musste, um überhaupt ohne einen Uni-Computer ins Internet kommen zu können, ist heute ein Leben ohne Browser-Plugins, zumindest für mich, nicht mehr vorstellbar. In den 90er gab es fast nur sinnvolle Inhalte im Internet, heute dagegen gibt es fast nur noch sinnlose Inhalte. Und deswegen sind die beiden wichtigsten aller Browser-Plugins Adblock und PwdHash: Adblock, um sich ungefragte Inhalte vom Leibe zu halten, und PwdHash, um sich unliebsame Zeitgenossen vom Leibe zu halten. Für beides gilt: Fehlanzeige auf einem iPhone!

Wenn man der Sache versucht auf den Grund zu gehen, stellt man fest, dass Apple anscheinend Browser-Plugins mit Gewalt verhindern will. Chrome für iPhone verfügt über keine Möglichkeit, Browser-Plugins zu verwenden und Firefox gibt es erst gar nicht. Und bei der erfolglosen Durchsicht der übrigen Browser-Varianten ist mir auch klar geworden, wo bei einem iPhone die Prioritäten liegen. Apple ist voll und ganz damit beschäftigt, die Bedürfnisse amerikanischer Prüderie zu befriedigen, und hat somit keine Zeit mehr, was Sinnvolles zu tun.

Man achte auf die folgende Klassifikation eines Internet-Browsers für das iPhone.

Dieser Browser verfügt über stark ausgeprägte Szenen mit erotischen Anspielungen, weswegen er erst mit 17 Jahren benutzt werden kann.

Eine viertel Stunde später: ich habe wieder eine trockene Hose an. Die alte musste ich leider wechseln, da ich mich vor lachen bepisst hatte.

Einem Browser zu attestieren, er sei Jugend gefährdend, ist ungefähr so hellsichtig wie einem Optiker zu unterstellen, er würde Prostitution fördern, weil man mit der Brille die Nutten erkennen kann. Aber gut, dass Apple uns das jetzt mal richtig klar gemacht hat. Und Brillen kaufen ist ja auch mitunter eine kostspielige Angelegenheit. Das Geld kann man ja viel besser in Apple-Produkte investieren. Das erinnert mich irgendwie an das Drama, eine Apple-ID ohne Kreditkarte zu bekommen. Aber das ist eine andere Geschichte...

Nun was ist das Fazit dieser Geschichte: ein Telefon bleibt ein Telefon und ist zu nichts mehr zu gebrauchen als zum telefonieren. Auch daran hat sich seit den 90er nichts geändert.

Sonntag, 9. November 2014

Combining the Bash nounset option with indirect expansion

Bash has a useful option called nounset. The option terminates the script if a variable is use, which has not been initialized. Using uninitialized values is a common error in script languages. Perl has introduced the strict package to address this kind of error and it is good Perl programing style to use it. The same applies to Bash: make set -u the first line after the shebang.

If you do so it becomes a bit more complicated to check, if a variable is set. The standard test will not work any more:

set -u
if [ -z "$VAR" ]; then
  echo 'VAR has no value.'
fi

Bash will terminate the script, because VAR is not set and there is no way to catch this exception. This means you have to avoid triggering nounset. This can be done with Bash's parameter expansion, in particular the "use default value" variant. The following code will not fail anymore:

set -u
if [ -z "${VAR:-}" ]; then
  echo 'VAR has no value.'
fi

Now the expression expands to the default value behind the hyphen, which is an empty string.

If you like to put the code into a function, it can be done this way:

set -u
require_value ()
{
  local VAR=$1
  local VAL=${!VAR}
  if [ -z "$VAL" ]; then
    die "Required value missing: $VAR"
  fi
}

The function require_value does another parameter expansion, the indirect expansion. The function takes the name of a variable as an argument and checks if the variable with the specified name has a value. This works as long as you do not enable the nounset option. If you enable it the function fails while setting the variable VAL.

The Bash manual is not very detailed about the question how to combine two parameter expansions. Trying to put them into each other fails.

$ a=b; echo ${${!a}:-}
bash: ${${!a}:-}: bad substitution

The answer is, that you can combine both notations into one parameter expansion and it happens just the right thing, which means the indirection is performed first and after that the default value gets applied.

set -u
require_value ()
{
  local VAR=$1
  local VAL=${!VAR:-}
  if [ -z "$VAL" ]; then
    die "Required value missing: $VAR"
  fi
}

Die Dreistigkeit der Placebo-Mafia

Unter der Domäne www.cialis20mgkaufen.net findet sich folgende schmucke Webseite.

Die Webseite betitelt sich selbst als "Geprüfter Deutscher Shop". Wenn man sich das Impressum der Seite ansieht, sieht man sofort, dass der Laden in der urdeutschen Gemeinde Venlo angesiedelt ist. Vielleicht war Deutschland in den Grenzen von Kaiser Karl dem Großen gemeint. Einem technisch versierten Beobachter fällt außerdem noch auf, dass das Impressum als Grafik hinterlegt ist. Dafür kann es eigentlich nur einen Grund geben: man will erreichen, dass die Information möglichst schlecht automatisch gelesen werden kann.

Wenn man sich dann den Inhalt der Whois-Datenbank für die DNS-Registrierung ansieht, stellt man fest, dass die Firma "Web Domains By Proxy" aus Pakistan die Domäne registriert hat. Man hat keine Mühen gescheut, seine Identität zu verschleiern.

Aber der größte Witz ist das Testergebnis von Stiftung Warentest. Angeblich wurden in Heft 06/2011 "Potenzmittel Online Apotheken aus Europa" getestet. Wer sich den Titel ausgedacht hat, sollte vielleicht beim Postillon anheuern. Wenn man sich also das tatsächliche Inhaltsverzeichnis von Heft 06/2011 ansieht, findet man den besagten Test natürlich nicht.

Vermutlich gilt das gleich für sämtliche anderen Logos auf der Seite: alles frei erfunden.

Sehr hübsch ist auch das Google+-Profil von unserem Apotheker.

Der gute Mann wohnt in Berlin und hat seine Versandlager laut Impressum in München, Venlo und UK. Die immense Reisetätigkeit, die eine solche Kombination nach sich zieht, ist vermutlich auch der Grund, warum er leider bislang noch keine Gelegenheit hatte, die deutsche Sprache zu lernen.

Wenn man dann das süße Profilfoto nimmt und bei Google eine Suche nach ähnlichen Bildern macht, findet man einen Dr. med. Ulrich Albers.

Man kann also mit ziemlicher Sicherheit sagen, dass auf der zitierten Webseite so ziemlich alles gelogen ist. Wer dort kauft, kann sein Geld auch direkt in den Gulli werfen. Ein Beispiel für die ganz alltägliche Internet-Abzocke.

Update

Eigenartiger Weise scheint Google ein Interesse daran zu haben, dass die Machenschaften von dubiosen Internet-Anbietern nicht veröffentlicht werden. Denn wie von Geisterhand sind die Screenshots, die ich von der dubiosen Webseite gemacht hatte, aus meinem Picasa-Konto gelöscht worden, ohne dass mich irgend jemand über diese Vorgänge informiert hat. Ich bin mal gespannt, ob die fleißige Bienchen, die sich für die Interessen von Internetbetrügern einsetzen, auch meinen Blog besuchen.

Montag, 3. November 2014

Emulating X11 selections on Windows

Putty

Putty can emulate the Xterm copy/paste style. It is not the default but it can easily activated

Emacs

In Emacs it is a bit more complicated. The following definitions are required in the .emacs file:

(setq select-active-regions nil)
(setq mouse-drag-copy-region t)
(global-set-key [mouse-2] 'mouse-yank-at-click)

Firefox

In Firefox the paste style can be activated in about:config. Search for "middle" and set middlemouse.paste to true.

In order to copy the selected text to the clipboard it is necessary to install an extension. AutoCopy 2 does the job.