Mikrotik RouterOS 6.38 IKEv2 Strongswan RSA Auth howto

Hi there,

a) setup clock of your routerboard

/system ntp client set primary-ntp=192.168.223.2
/system clock set time-zone-name=Europe/Vienna

b) generate certificates

/certificate add common-name="paranoids.at Root CA" name=ca     
/certificate sign ca ca-crl-host=192.168.223.106
/certificate add common-name=test.paranoids.at subject-alt-name=IP:test.paranoids.at key-usage=tls-server name=server1
/certificate sign server1 ca=ca
/certificate add common-name=client1@test.paranoids.at key-usage=tls-client name=client1
/certificate sign client1 ca=ca

c) configure your server

/export compact                                                      
# jan/06/2017 12:21:49 by RouterOS 6.38
#
/ip ipsec proposal
set [ find default=yes ] auth-algorithms=sha256 enc-algorithms=aes-256-cbc pfs-group=modp2048
/ip pool
add name=pool1 ranges=192.168.33.0/27
/ip ipsec mode-config
add address-pool=pool1 address-prefix-length=32 name=test
/ip address
add address=192.168.99.1/24 interface=ether2 network=192.168.99.0
/ip dhcp-client
add dhcp-options=hostname,clientid disabled=no interface=ether1
/ip dns static
add address=192.168.223.106 name=test
/ip ipsec peer
add address=0.0.0.0/0 auth-method=rsa-signature certificate=server1 dh-group=modp2048 enc-algorithm=aes-256 exchange-mode=ike2 generate-policy=port-strict hash-algorithm=sha256 \
    mode-config=test passive=yes
/ip ipsec policy
set 0 dst-address=192.168.33.0/27 src-address=0.0.0.0/0

d) export client certificates

/certificate export-certificate ca
/certificate export-certificate client1 export-passphrase=1234567890

e) import client certificates to strongswan (file ending is important)

 scp admin@192.168.223.106:/cert_export_client1.crt .
 scp admin@192.168.223.106:/cert_export_client1.key .
 scp admin@192.168.223.106:/cert_export_client1.key .
 mv cert_export_ca.crt /etc/ipsec.d/cacerts/cert_export_ca.pem
 mv cert_export_client1.crt /etc/ipsec.d/certs/cert_export_client1.pem
 mv cert_export_client1.key /etc/ipsec.d/private/cert_export_client1.pem

f) configure strongswan properly

/etc/ipsec.conf

conn test
 keyexchange=ikev2
 ike=aes256-sha256-modp2048
 esp=aes256-sha256-modp2048
 ikelifetime = 24h
 lifetime = 30m
 dpddelay = 120s
 left=%defaultroute
 leftsourceip=%config
 leftcert=cert_export_client1.pem
 leftid=client1@test.paranoids.at
 leftfirewall=yes
 right=192.168.223.106
 rightsubnet=192.168.99.0/24
 rightid="CN=test.paranoids.at" 
 auto=add

/etc/ipsec.secrets

: RSA cert_export_client1.pem "1234567890"

g) fire up your vpn

:~# systemctl restart strongswan
:~# ipsec up test

Resources:
https://wiki.strongswan.org/projects/strongswan/wiki/IKEv2Examples
http://wiki.mikrotik.com/wiki/Manual:IP/IPsec#Ikev2_Server_Setup

Hint:
For strongswan under Debian Jessie you have to remove the passphrase from the private key!
For Android set Server-Identity: CN=test.paranoids.at!

Have fun!

Simple PHP Mysql Bind dynamic DNS Service

Hi

Need a simple dyndns service.
Here my crappy 10 minutes approach to get this done:

curl -> webserver -> mysql -> cronjob -> namedZoneFile

Here my curl client cronjob every minute:

/usr/bin/curl --silent --user username:password http://dyn.xxx.xx

Webserver PHP implementation:

.htaccess

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>

index.php

<?php

$ipAddress = $_SERVER['REMOTE_ADDR'];

if (!isset($_SERVER['PHP_AUTH_USER'])) {
  header('WWW-Authenticate: Basic realm="paranoids.at DynDns"');
  header('HTTP/1.0 401 Unauthorized');
  echo 'No Auth, Try again';
} 
else {
  $isAuth = getUserPass($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
  if (!empty($isAuth)) {
    if (empty(ifHostExists($isAuth['id']))) {
      insertHost($isAuth['id'], $ipAddress);
    }
    else {
      $host = ifHostExists($isAuth['id']);
      if (strcmp($host['ip'], $ipAddress) !== 0) {
        updateHost($host['userid'], $ipAddress);
      } 
    }
  }
  else {
    echo 'Wrong Auth, Try again';
  }
}

connect_db_dyn()->close();

function ifHostExists($userid) {
  $result = connect_db_dyn()->query("SELECT * FROM host WHERE userid='$userid';");
  return $result->fetch_assoc();
}

function getUserPass($user,$pass) {
  $result = connect_db_dyn()->query("SELECT * FROM user WHERE username='$user' AND password='$pass' LIMIT 1;");
  return $result->fetch_assoc();
}

function insertHost($userid,$newip) {
  connect_db_dyn()->query("INSERT INTO host (userid, ip, changed) VALUES ('$userid', '$newip', '1');");
}

function updateHost($userid,$ip) {
  connect_db_dyn()->query("UPDATE host SET ip='$ip', changed=1, timestamp=CURRENT_TIMESTAMP WHERE userid='$userid';");
}

function connect_db_dyn() {
  $dbh = new mysqli('localhost', 'username', 'password', 'database');
  return $dbh;
}

?>

Database dump:

-- phpMyAdmin SQL Dump
-- version 4.6.4
-- https://www.phpmyadmin.net/
--
-- Host: localhost

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

--
-- Database: `database`
--

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

--
-- Table structure for table `host`
--

CREATE TABLE `host` (
 `id` int(11) NOT NULL,
 `userid` int(11) NOT NULL,
 `ip` varchar(255) NOT NULL,
 `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
 `changed` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `host`
--

INSERT INTO `host` (`id`, `userid`, `ip`, `timestamp`, `changed`) VALUES
(14, 1, '1.1.1.1', '2016-11-30 04:38:03', 0);

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

--
-- Table structure for table `user`
--

CREATE TABLE `user` (
 `id` int(11) NOT NULL,
 `username` varchar(255) NOT NULL,
 `password` varchar(255) NOT NULL,
 `comment` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `user`
--

INSERT INTO `user` (`id`, `username`, `password`, `comment`) VALUES
(1, 'username1', 'password1', 'comment1');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `host`
--
ALTER TABLE `host`
 ADD PRIMARY KEY (`id`);

--
-- Indexes for table `user`
--
ALTER TABLE `user`
 ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `host`
--
ALTER TABLE `host`
 MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15;
--
-- AUTO_INCREMENT for table `user`
--
ALTER TABLE `user`
 MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;

dnsserverside cronjob every minute:

<?php

if (!empty(getChange())) {
 deleteHosts();
 updateHosts();
 writeBind();
}

connect_Db_Dyn()->close();

function getChange() {
 $result = connect_Db_Dyn()->query("SELECT * FROM host WHERE changed = 1");
 return $result->fetch_assoc();
}

function getHosts() {
 $result = connect_Db_Dyn()->query("SELECT * FROM host");
 return $result->fetch_all($resulttype = MYSQLI_ASSOC);
}

function deleteHosts() {
 connect_Db_Dyn()->query("DELETE FROM host WHERE timestamp < date_add(current_date, interval -14 day) LIMIT 1000;");
}

function updateHosts() {
 connect_Db_Dyn()->query("UPDATE host SET changed=0;");
}

function getUsernameById($userid) {
 $result = connect_Db_Dyn()->query("SELECT username FROM user WHERE id='$userid'");
 $row = $result->fetch_assoc();
 return $row['username'];
}

function connect_Db_Dyn() {
 $dbh = new mysqli('localhost', 'username', 'password', 'database');
 return $dbh;
}

function writeBind() {
$date = new DateTime();
$texthead = '$TTL 60
@ IN SOA ns1.xxxx.xx. hostmaster.xxxx.xxx. (
 sedSerial ; serial, unix timestamp  #
 7200 ; refresh, seconds
 540 ; retry, seconds
 604800 ; expire, seconds
 3600 ) ; minimum, seconds
;'."\n\n";

$texthead = preg_replace("/sedSerial/",$date->getTimestamp(),$texthead);

$textbody = "@"."\t"."A"."\t"."1.1.1.1"."\n";

foreach (getHosts() as $host) {
 $textbody .= getUsernameById($host['userid'])."\t"."A"."\t".$host['ip']."\n";
}

$textfooter = '
@ NS ns2.xxx.xx.
@ NS ns1.xxx.xx.
';
$file = $texthead.$textbody.$textfooter;

file_put_contents("/etc/bind/dns.xxx.xx", $file);

system('/usr/sbin/rndc -q reload');

}

?>

Bind named.conf:

zone "dns.xxx.xx" {
 type master;
 allow-transfer {1.1.1.1;2:1:1::2;};
 file "/etc/bind/dns.xxx.xx";
};

Have fun!

Debian on Barracuda NG F10 Firewall

Hi

While I was tearing down the firewall the CF-Slot jumped right into my eyes. Every Linux guy might think the same. 🙂

So i debootstraped a CF-card made it bootable and right after the first try, bam, working.
The Hardware got freed from the propritary Linux OS and crappy tools and … Yes the backdoors, bugs and security holes, because you won’t get any free downloadable firmware updates. This is really annoying on Barracuda firewalls. It’s a shitty firewall. Every crappy TP-Link does the same things in production.

Have fun!

Monitor the RAID Status Avago LSI Logic SAS3008 Fusion-MPT SAS-3 with Linux

Hi

Need to monitor the RAID Status of your Avago LSI Logic / Symbios Logic SAS3008 PCI-Express Fusion-MPT SAS-3 under Linux with perl?

Yes Avago has a crappy website. When you search the website for SAS3008 you only find some pdf. But not the utility to query your raid controller. Crappy website or intentionally. Who knows 🙂

Below is a script which send’s a simple mail if something goes bad to your RAID. Just put it in your crontab. Might someone want’s to adopt it. Might use with Nagios/Icinga. Actually I’ve not the case to do this. Might later…

#!/usr/bin/perl

use warnings;
use MIME::Lite;

$emailFrom = 'root@server.domain.tld';
$emailTo = 'hostmaster@yourdomain.tpl';
$smartHost = 'smarthost.mail.local';
$hostName = 'server.domain.tld';
$pathSas3ircu = '/root/bin/SAS3IRCU_P12/sas3ircu_linux_x64_rel/sas3ircu';

if (check_status() == 1) {
  $body = join("", get_info("0","STATUS"));
  send_email($emailTo,$body);
}

sub check_status {
  $error = 0;

  foreach $line (get_info("0","DISPLAY")) {
    if ($line =~ /Status of volume/) {
      if ($line !~/Okay/) {
        $error = 1;
      }
    }
    if ($line =~ /State/) {
      if ($line !~ /Optimal/ ) {
        $error = 1;
      }
    }
  }
  return $error;
}

sub get_info {
  $arg1 = shift;
  $arg2 = shift;

  $cmd = "$pathSas3ircu $arg1 $arg2";
  @output = `$cmd`;
  return @output;
}

sub send_email {
  $arg1 = shift;
  $arg2 = shift;
  
  $subject = "Warning RAID inconsitent $hostName";

  $msg = MIME::Lite->new(
    From     => $emailFrom,
    To       => $arg1,
    Subject  => $subject,
    Data     => $arg2
  );

  $msg->send('smtp',$smartHost,Debug=>0);
}

Here a download link of the tool:
http://docs.avagotech.com/docs/SAS3IRCU_P12.zip

Here a link of an different controller where you find the download link:
http://www.avagotech.com/products/server-storage/host-bus-adapters/sas-9305-16e#downloads

EDIT 16.05.2018:
TomD kindly provided a simple nagios script:

#!/bin/bash

status=$(sas3ircu 0 STATUS | grep -o 'Optimal')
status1=$(sas3ircu 0 DISPLAY | grep -o 'OKY')

if [ "$status" =  "Optimal" ]
        then 
        if [ "$status1" =  "OKY" ]
                then 
                echo OK raid is good
                exit 0
fi
else
        echo Warn raid failed
        exit 1
fi

echo Critical raid failed
exit 3

Have Fun!

Geiger Counter Visualisation

Hi there!

I build a visualisation (php javascript html5 chart.js mysql perl) for my Arduino Geiger Counter. Here some screenshots.

I’m no professional programmer. But it does what it should. Might someone find this useful.
Here the downloadlink.

https://www.paranoids.at/downloads/geiger-f5b7681.tar.gz

Just import the .sql files, connect the arduino via usb, change data formatting if needed and start logGeiger.pl.

Happy plotting 🙂