Thursday, December 10, 2015

[Zabbix] How to execute a script if your host/website is down in Zabbix

Zabbix is a bit confusing for beginners so here a quick tutorial how to simply execute a script, in my case it was used for a failover actions (mysql slave to master promotion and DNS ip change).

First of all you have to understand the way of how things work in Zabbix:

(more here: http://www.zbxtutorials.org/2012/10/z20g001-terminology.html )

Let's start by setting up a web scenario:
Go Configuration -> Hosts, pick a host that will do the monitoring (I often use the zabbix server itself), click web(0) and right upper corner "create scenario" (read wiki how to, but its easy)

Next step we find out what the event is called since we need this for our trigger expression: Go to Monitoring -> Latest Data -> Show Filter (small the center of screen), pick your host and filter, under other you'll find web.test.fail[site test](name depends on your setup) and its last value 0, this will jump to 1 if the site is not reachable.

edit: IN ZABBIX 3.0 you gotta check "Show Details" to see key names

Next step we will create a trigger: Configuration -> Hosts -> pick Host -> Triggers -> create new trigger upper right corner: expression should look like this "{YOURHOSTNAME:web.test.fail[site test].last()}>0"

Next step create an Action: Configuration -> Actions -> Create Action:
You only have to set name, under conditions remove the given ones and under New condition pick "trigger" "like" and your trigger name which should be auto-suggested. Under Operations click new, Operation Type : Remote Command, Target add new Current Host, Execute on...your choice, Type Custom script and enter your commands.

That is it.

I recommend not sending sensitive information in the commands, if you have such then just put the commands in a script at the agent server and execute them with "/bin/bash /path/script.sh"

Saturday, November 21, 2015

Varnish 4.1 + Hitch SSL/TLS Termination via PROXY protocol default.vcl for Drupal 7

Hitch (https://hitch-tls.org/) config. The [] on ipv4 are weird but necessary! The pem file needs to be cat'd in following order: privkey cert intermediates dhparameter
# Listening
frontend = "[xxx.xxx.xxx.xxx]:443"
ciphers  = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
# Send traffic to the varnish backend
backend        = "[192.168.104.8]:80"
#use PROXY protocol
write-proxy-v2 = on
pem-file = "/etc/ssl/private/mysite.com.pem"

Information on PROXY protocol: http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt

Varnish needs to be called with:
varnishd -a :80,PROXY -T localhost:6082 -f /etc/varnish/default.vcl.......
Varnish default.vcl:

vcl 4.0;
import std;
backend default {
    .host = "127.0.0.1";
    .port = "81";
}
sub vcl_recv {
  # Use anonymous, cached pages if all backends are down.
  if (!std.healthy(req.backend_hint)) {
    unset req.http.Cookie;
  }
  # Do not cache these paths.
  if (req.url ~ "^/status\.php$" ||
      req.url ~ "^/update\.php$" ||
      req.url ~ "^/admin$" ||
      req.url ~ "^/admin/.*$" ||
      req.url ~ "^/flag/.*$" ||
      req.url ~ "^.*/ajax/.*$" ||
      req.url ~ "^.*/ahah/.*$") {
       return (pass);
  }
  # Always cache the following file types for all users.
  if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
    unset req.http.Cookie;
  }
  # Remove all cookies that Drupal doesn't need to know about.
  if (req.http.Cookie) {
    set req.http.Cookie = ";" + req.http.Cookie;
    set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");   
    set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
    if (req.http.Cookie == "") {
      unset req.http.Cookie;
    }
    else {
      return (pass);
    }
  }
}
# Set a header to track a cache HIT/MISS.
sub vcl_deliver {
  if (obj.hits > 0) {
    set resp.http.X-Varnish-Cache = "HIT";
  }
  else {
    set resp.http.X-Varnish-Cache = "MISS";
  }
}
sub vcl_backend_response {
  if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
    set beresp.ttl = 10m;
  }
  if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
    unset beresp.http.set-cookie;
  }
  # Allow items to be stale if needed.
  set beresp.grace = 6h;
}
# In the event of an error, show friendlier messages.
sub vcl_backend_error {
  set beresp.http.Content-Type = "text/html; charset=utf-8";
  synthetic({"
<html>
<head>
  <title>Page Unavailable</title>
  <style>
    body { background: #303030; text-align: center; color: white; }
    #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0; padding: 30px; background: #323232; }
    a, a:link, a:visited { color: #CCC; }
    .error { color: #222; }
  </style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)">
  <div id="page">
    <h1 class="title">Page Unavailable</h1>
    <p>The page you requested is temporarily unavailable.</p>
    <p>We're redirecting you to the <a href="/">homepage</a> in 5 seconds.</p>
    <div class="error">(Error "} + beresp.status + " " + beresp.reason + {")</div>
  </div>
</body>
</html>
"});
  return (deliver);
}

sub vcl_synth {

  set resp.http.Content-Type = "text/html; charset=utf-8";
  synthetic({"
<html>
<head>
  <title>Page Unavailable</title>
  <style>
    body { background: #303030; text-align: center; color: white; }
    #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0; padding: 30px; background: #323232; }
    a, a:link, a:visited { color: #CCC; }
    .error { color: #222; }
  </style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)">
  <div id="page">
    <h1 class="title">Page Unavailable</h1>
    <p>The page you requested is temporarily unavailable.</p>
    <p>We're redirecting you to the <a href="/">homepage</a> in 5 seconds.</p>
    <div class="error">(Error "} + resp.status + " " + resp.reason + {")</div>
  </div>
</body>
</html>
"});
  return (deliver);
}

How to set permissions on thousands of files in a AWS S3 bucket using s3cmd

We use xargs to run parallel processes, flag P specifies number of processes.
First we get all paths on S3+Filenames

s3cmd --recursive ls s3://mys3bucket/ | awk -F' ' '{print $4;}' | sort | uniq > paths.txt
Then we set permissions, in this case we set them to public, adjust for what you need!

cat paths.txt | xargs -P20 -I% s3cmd setacl --acl-public "%"

Friday, November 20, 2015

a working Varnish 4.1 VCL config for Drupal 7


vcl 4.0;
import std;
backend default {
    .host = "127.0.0.1";
    .port = "81";
}
sub vcl_recv {
  # Use anonymous, cached pages if all backends are down.
  if (!std.healthy(req.backend_hint)) {
    unset req.http.Cookie;
  }
  if (req.restarts == 0) {
    if (req.http.x-forwarded-for) {
      set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    }
    else {
      set req.http.X-Forwarded-For = client.ip;
    }
  }
  # Do not cache these paths.
  if (req.url ~ "^/status\.php$" ||
      req.url ~ "^/update\.php$" ||
      req.url ~ "^/admin$" ||
      req.url ~ "^/admin/.*$" ||
      req.url ~ "^/flag/.*$" ||
      req.url ~ "^.*/ajax/.*$" ||
      req.url ~ "^.*/ahah/.*$") {
       return (pass);
  }
  # Always cache the following file types for all users. This list of extensions
  # appears twice, once here and again in vcl_backend_response so make sure you edit both
  # and keep them equal.
  if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
    unset req.http.Cookie;
  }
  # Remove all cookies that Drupal doesn't need to know about. We explicitly
  # list the ones that Drupal does need, the SESS and NO_CACHE. If, after
  # running this code we find that either of these two cookies remains, we
  # will pass as the page cannot be cached.
  if (req.http.Cookie) {
    # 1. Append a semi-colon to the front of the cookie string.
    # 2. Remove all spaces that appear after semi-colons.
    # 3. Match the cookies we want to keep, adding the space we removed
    #    previously back. (\1) is first matching group in the regsuball.
    # 4. Remove all other cookies, identifying them by the fact that they have
    #    no space after the preceding semi-colon.
    # 5. Remove all spaces and semi-colons from the beginning and end of the
    #    cookie string.
    set req.http.Cookie = ";" + req.http.Cookie;
    set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");   
    set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
    if (req.http.Cookie == "") {
      # If there are no remaining cookies, remove the cookie header. If there
      # aren't any cookie headers, Varnish's default behavior will be to cache
      # the page.
      unset req.http.Cookie;
    }
    else {
      # If there is any cookies left (a session or NO_CACHE cookie), do not
      # cache the page. Pass it on to Apache directly.
      return (pass);
    }
  }
}
# Set a header to track a cache HIT/MISS.
sub vcl_deliver {
  if (obj.hits > 0) {
    set resp.http.X-Varnish-Cache = "HIT";
  }
  else {
    set resp.http.X-Varnish-Cache = "MISS";
  }
}
# Code determining what to do when serving items from the Apache servers.
# beresp == Back-end response from the web server.
sub vcl_backend_response {
  # We need this to cache 404s, 301s, 500s. Otherwise, depending on backend but
  # definitely in Drupal's case these responses are not cacheable by default.
  if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
    set beresp.ttl = 10m;
  }
  # Don't allow static files to set cookies.
  # (?i) denotes case insensitive in PCRE (perl compatible regular expressions).
  # This list of extensions appears twice, once here and again in vcl_recv so
  # make sure you edit both and keep them equal.
  if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
    unset beresp.http.set-cookie;
  }
  # Allow items to be stale if needed.
  set beresp.grace = 6h;
}
# In the event of an error, show friendlier messages.
sub vcl_backend_error {
  # Redirect to some other URL in the case of a homepage failure.
  #if (bereq.url ~ "^/?$") {
  #  set beresp.status = 302;
  #  set beresp.http.Location = "http://backup.example.com/";
  #}
  # Otherwise redirect to the homepage, which will likely be in the cache.
  set beresp.http.Content-Type = "text/html; charset=utf-8";
  synthetic({"
<html>
<head>
  <title>Page Unavailable</title>
  <style>
    body { background: #303030; text-align: center; color: white; }
    #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0; padding: 30px; background: #323232; }
    a, a:link, a:visited { color: #CCC; }
    .error { color: #222; }
  </style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)">
  <div id="page">
    <h1 class="title">Page Unavailable</h1>
    <p>The page you requested is temporarily unavailable.</p>
    <p>We're redirecting you to the <a href="/">homepage</a> in 5 seconds.</p>
    <div class="error">(Error "} + beresp.status + " " + beresp.reason + {")</div>
  </div>
</body>
</html>
"});
  return (deliver);
}

sub vcl_synth {

  set resp.http.Content-Type = "text/html; charset=utf-8";
  synthetic({"
<html>
<head>
  <title>Page Unavailable</title>
  <style>
    body { background: #303030; text-align: center; color: white; }
    #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0; padding: 30px; background: #323232; }
    a, a:link, a:visited { color: #CCC; }
    .error { color: #222; }
  </style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)">
  <div id="page">
    <h1 class="title">Page Unavailable</h1>
    <p>The page you requested is temporarily unavailable.</p>
    <p>We're redirecting you to the <a href="/">homepage</a> in 5 seconds.</p>
    <div class="error">(Error "} + resp.status + " " + resp.reason + {")</div>
  </div>
</body>
</html>
"});
  return (deliver);
}

Monday, October 26, 2015

Nginx and Apache for Drupal

Here is a config for Nginx serving all static content and Apache serving dynamic.

server {
        listen 80;
    server_name bla.com;
    root /var/www/htlm;

    index index.html index.htm index.php;

    access_log /var/log/nginx/example.org.access.log;
    error_log /var/log/nginx/example.org.error.log;

    location = /favicon.ico {
            log_not_found off;
            access_log off;
    }

    location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
    }

    # For drush
    location = /backup {
            deny all;
    }

    # Prevent user from accessing settings.php directly
    location ~ ^/sites/[^/]+/settings.php$ {
            deny all;
    }

    ## Replicate the Apache <FilesMatch> directive of Drupal standard
    ## .htaccess. Disable access to any code files. Return a 404 to curtail
    ## information disclosure. Hide also the text files.
    location ~* ^(?:.+.(?:htaccess|make|txt|log|engine|inc|info|install|module|profile|po|sh|.sql|theme|tpl(?:.php)?|xtmpl)|code-style.pl|/Entries.|/Repository|/Root|/Ta$
            return 404;
    }

    location ~ ../..php$ {
            return 403;
    }

    location / {
        try_files $uri $uri/ @apache;
        expires max;
        access_log off;

    }

    location @apache {
                proxy_pass  http://127.0.0.1:8888;
     }

    # Use an SSH tunnel to access those pages. They shouldn't be visible to
    # external peeping eyes.
    location = /install.php {
            allow 127.0.0.1;
            deny all;
    }

    location = /update.php {
            allow 127.0.0.1;
            deny all;
    }

}

Saturday, October 3, 2015

How to put Debian preseed file on a iso/cd image

In Debian you need package genisoimage instead of mkisofs! In other distros use mkisofs

#!/bin/sh

if [ $# -ne 3 ]
then
 echo "Usage: $0 input.iso output.iso your-preseed-file"
 exit 1
fi
iso=$1
output=$2
preseed=$3
lpdir=__loopdir__
cddir=__cd__
irdir=__irmod__

# Copy image
mkdir $lpdir
mount -o loop $iso $lpdir
rm -rf $cddir
mkdir $cddir
rsync -a -H --exclude=TRANS.TBL $lpdir/ $cddir
umount $lpdir

# Hack initrd
mkdir $irdir
cd $irdir
gzip -d < ../$cddir/install.amd/initrd.gz | \
 cpio --extract --verbose --make-directories --no-absolute-filenames
cp ../$preseed preseed.cfg
find . | cpio -H newc --create --verbose | \
 gzip -9 > ../$cddir/install.amd/initrd.gz
cd ../
rm -rf $irdir

# Modify default option
cd $cddir/isolinux
sed 's/timeout 0/timeout 5/' isolinux.cfg > tmp
mv tmp isolinux.cfg

#uncomment next 2 lines if wished
#sed 's/vga=788/console=ttyS0,9600n8/' txt.cfg > tmp
#mv tmp txt.cfg

cd ../../
# Fix checksum
cd $cddir
md5sum `find -follow -type f` > md5sum.txt
cd ..

# Create bootable CD
genisoimage -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat ./$cddir

# Cleaning up
rm -rf $lpdir
rm -rf $cddir

echo "Created $output!"

Debian 8 Jessie Preseed Example

Here you find the full example preseed file for Jessie:
https://www.debian.org/releases/jessie/example-preseed.txt

I personally wanted an attended installation that just had some options preconfigured and runs a late_command in the end:

#### Contents of the preconfiguration file (for jessie)
### Localization
# Preseeding only locale sets language, country and locale.
d-i debian-installer/locale string en_US
d-i keyboard-configuration/xkb-keymap select us

### Network configuration
# Disable network configuration entirely. This is useful for cdrom
# installations on non-networked devices where the network questions,
# warning and long timeouts are a nuisance.
d-i netcfg/choose_interface select eth1
popularity-contest popularity-contest/participate boolean false
# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note

#copy another script to the target
d-i preseed/late_command string wget -O /target/etc/init.d/latecommand.sh http://10.0.8.1/latecommand.sh; \
in-target chmod +x /etc/init.d/latecommand.sh; \
in-target update-rc.d latecommand.sh defaults

Friday, October 2, 2015

Proxmox V4 Nginx Reverse Proxy with VNC

After many many fails now a working one. This is for https://domain.tld/proxmox:

 location ~ ^/(?:proxmox|pve2|api2|novnc)$ {
    rewrite /(proxmox|pve2|api2|novnc) /$1/ permanent;
  }
  location ~ ^/(?:proxmox|pve2|api2|novnc)/ {
    rewrite /proxmox/(.*) /$1 break;
    rewrite /((?:pve2|api2|novnc)/.*) /$1 break;
    proxy_pass https://xxx.xxx.xxx.xxx:8006;
    proxy_read_timeout 90;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Connection "upgrade";
    proxy_set_header Origin http://$host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

Thursday, August 20, 2015

How to Fix Seafile Client "connecting to server" loop

If you run your own server with a self signed ssl certificate and your client goes "connecting to server" but nothing happens check in options of the client and activate "do not verify server certificate in HTTPS syncing".

Wednesday, August 19, 2015

Odysseus and Privacy

"Odysseus wept when he heard the poet sing of his great deeds abroad because, once sung, they were no longer his alone. They belonged to anyone who heard the song." - Ward Just (2004)

Thursday, July 16, 2015

How To compile/create OpenVPN with installer for Windows on Linux (Debian Jessie)

# apt-get install build-essential mingw-w64 tofrodos dh-autoreconf nsis
# cd /usr/bin
# ln -s fromdos dos2unix
# ln -s todos unix2dos

To customize the build options, refer to build.vars in openvpn-build/generic, it contains the defaults for building, most settings can be customized by setting environment variable before executing the build script.

The following will produce the OpenVPN Setup for 32 and 64 bit Windows.
$ git clone https://github.com/OpenVPN/openvpn-build.git
$ cd openvpn-build/windows-nsis
$ ./build-snapshot

Monday, July 13, 2015

HowTo compile OpenVPN + obfuscation with xorpatch on Debian

  1. # apt-get install build-essential libssl-dev liblzo2-dev libpam0g-dev easy-rsa 
  2. # wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.7.tar.xz
  3. # wget https://raw.githubusercontent.com/clayface/openvpn_xorpatch/master/openvpn_xor.patch
  4. # tar xvf openvpn-2.3.7.tar.xz
  5. # cd openvpn-2.3.7.tar.xz
  6. # patch -p1 < ../openvpn_xor.patch
  7. # ./configure
  8. # ./make
  9. # ./make install

You need to put one of the following options in server.conf and client config! 
"scramble reverse" - This simply reverses all the data in the packet. This is enough to get past the regular expression detection in both China and Iran.
"scramble xorptrpos" - This performs a xor operation, utilizing the current position in the packet payload.
"scramble obfuscate password" - This method is more secure. It utilizes the 3 types of scrambling mentioned above. "password" is the string which you want to use.

How To setup OpenVPN from scratch with PAM authentication on Debian Jessie

Quick How To:
  1. # apt-get install build-essential libssl-dev liblzo2-dev libpam0g-dev easy-rsa
  2. wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.7.tar.xz
  3. # tar xvf openvpn-2.3.7.tar.xz
  4. # ./configure
  5. # ./make
  6. # ./make install

For basic setup and key generation see: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-14-04


For PAM:

1. in server config put: 
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn

2. create new pam file: nano /etc/pam.d/openvpn

auth    required        pam_unix.so    shadow    nodelay
account required        pam_unix.so

3. add "auth-user-pass" in client config

Saturday, July 4, 2015

Configuring Ejabberd with PAM Authentication for specific group

Quick Tutorial because I had to figure this out on my own and it took a while to get everything working in the correct way.

OS Debian Jessie, Ejabberd 14.07

1. service ejabberd stop
2. edit /etc/ejabberd/ejabberd.yml
##
## Authentication using PAM
##
auth_method: pam
pam_service: "ejabberd"
!!!DO NOT FORGET TO DISABLE auth_method: internal further up the config!!!
 3. nano /etc/login.group.allowed (you can name that file w/e you want)
     users (in my case the group is called users)
 4. nano /etc/pam.d/ejabberd

#%PAM-1.0
auth       include  common-password
account    required pam_listfile.so item=group sense=allow file=/etc/login.group.allowed onerr=fail
account    include  common-password

 5. service ejabberd start

 6. Don't forget that the user ejabberd needs to have access to the shadow file, so you might have to create a shadow group and chroot /etc/shadow to allow access

Monday, June 29, 2015

Proxmox Host and Nodes with Private IP - NAT and Port Forwarding

Here a quick solution for playing around when you only have 1 public IP and private IPs for your VMs/Nodes. Here we give 10.10.10.2 to your VM and forward port 10022 to port 22 (SSH) on the VM

Host Config:
auto eth0
iface eth0 inet static
        address 94.xxxxxxxxx
        netmask 255.255.255.0
        broadcast 94.xxxxxxxxx
auto vmbr0
iface vmbr0 inet static
        address  10.10.10.1
        netmask  255.255.255.0
        bridge_ports none
        bridge_stp off
        bridge_fd 0
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up   iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o eth0 -j MASQUERADE
                post-up iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 10022 -j DNAT --to-destination 10.10.10.2:22
        post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o eth0 -j MASQUERADE

Node/VM Config:
auto eth0
iface eth0 inet static
         address 10.10.10.2
         gateway 10.10.10.1
         netmask 255.255.255.0


Friday, March 27, 2015

96h virtualization learning marathon

In the last 96h I had a learning marathon. Things I checked out in more or less detail:
  • Openstack
  • Proxmox
  • oVirt
  • Docker
  • OpenVZ
  • KVM libvirt
  • CoreOS
  • mdadm software raid config