Monday, October 10, 2016

PHP >5.3: DateTime

Example construct Datetime object

$datetime = new DateTime("now");
$datetime = new DateTime('2000-01-01');

Example to print Datetime

echo $datetime->format('Y-m-d\TH:i:s');

Example to add a hour

$datetime->add(new DateInterval('PT1H'));

Example to add 10 day

$datetime->add(new DateInterval('P10D'));
Note:
  • P: Period
  • T: Time

Comparing 2 Datetime

$datetime = new DateTime('2016-10-10');
$datetime2 = new DateTime('2016-10-9');
echo var_dump($datetime > $datetime2).' $datetime > $datetime2 <br>'; // bool(true) $datetime > $datetime2 
echo var_dump($datetime < $datetime2).' $datetime < $datetime2 <br>'; // bool(false) $datetime < $datetime2 


References:

Thursday, October 6, 2016

Debian Jessie: installing fail2ban 0.9.5-1 from SID with ipset

Debian Jessie stable contain old version of fail2ban, i.e. fail2Ban v0.8.13 (Debian 8.6). This version has reach end of life cycle from its developer. Current version (in active) development is version 0.10. Debian Jessie in SID (unstable) has version 0.9.5-1. We are going to use this version on our production server.
Our /etc/apt/sources.list, we don't add any SID repository to our sources.
deb http://kambing.ui.ac.id/debian/ jessie main
deb-src http://kambing.ui.ac.id/debian/ jessie main

deb http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main

#backport
deb http://ftp.debian.org/debian jessie-backports main
Before download and install fail2ban, install all required package from this article
Download fail2ban 0.9.5-1 installer from SID directly from main pool
or from its mirror (choose your closest one)
Use wget to retrieve fail2ban 0.9.5-1 installer
# wget http://kambing.ui.ac.id/debian/pool/main/f/fail2ban/fail2ban_0.9.5-1_all.deb
If you are not confidence to use "unstable" version use fail2ban 0.9.3-1 from testing
Remove existing fail2ban
# apt-get --purge remove fail2ban
You can now start to install fail2ban 0.9.5-1
# dpkg -i fail2ban_0.9.5-1_all.deb
(Reading database ... 109167 files and directories currently installed.)
Preparing to unpack fail2ban_0.9.5-1_all.deb ...
Unpacking fail2ban (0.9.5-1) over (0.9.5-1) ...
dpkg: dependency problems prevent configuration of fail2ban:
 fail2ban depends on python3:any (>= 3.3.2-2~).

dpkg: error processing package fail2ban (--install):
 dependency problems - leaving unconfigured
Processing triggers for systemd (215-17+deb8u5) ...
Processing triggers for man-db (2.7.0.2-5) ...
Errors were encountered while processing:
 fail2ban
It will ask you to install python python3. It's file and safe, your default python still 2.7. Run this command to fix it.
# apt-get -f install
...
# python --version
Python 2.7.9
Create a new action in /etc/fail2ban/action.d/iptables-ipset-proto4-allports.conf
# Fail2Ban configuration file
# Original: iptables-ipset-proto4.conf (Author: Daniel Black)
# Modified: IGAM Muliarsa
#
# Tested on: Debian 8.6
# ipset version: ipset v6.23, protocol version: 6
[INCLUDES]
before = iptables-common.conf
[Definition]
# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = ipset --create f2b-<name> iphash
              <iptables> -I <chain> -m set --match-set f2b-<name> src -j <blocktype>
# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop = <iptables> -D <chain> -m set --match-set f2b-<name> src -j <blocktype>
             ipset --flush f2b-<name>
             ipset --destroy f2b-<name>
# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = ipset --test f2b-<name> <ip> ||  ipset --add f2b-<name> <ip>
# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionunban = ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
[Init]
You need to enable configure /etc/fail2ban/fail.conf and enabling ipset
...
# consider low maxretry and a long bantime
bantime  = 600
...
maxretry = 5
...
[sshd]

port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
enabled = true
filter = sshd
action = iptables-ipset-proto4[name=sshd]
...
[sshd-ddos]
# This jail corresponds to the standard configuration in Fail2ban.
# The mail-whois action send a notification e-mail with a whois request
# in the body.
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
enabled = true
filter = sshd
action = iptables-ipset-proto4[name=sshd-dos]
...
[proftpd]
port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(proftpd_log)s
backend  = %(proftpd_backend)s
enabled = true
filter = proftpd
action = iptables-ipset-proto4-allports[name=proftpd]
...
[postfix]

port     = smtp,465,submission
logpath  = %(postfix_log)s
backend  = %(postfix_backend)s
enabled = true
filter = postfix
action = iptables-ipset-proto4[name=postfix, port="25,465,993,995,465,143,110"]
...
[postfix-sasl]

port     = smtp,465,submission,imap3,imaps,pop3,pop3s
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath  = %(postfix_log)s
backend  = %(postfix_backend)s
enabled = true
filter = postfix-sasl
action = iptables-ipset-proto4[name=postfix-sasl, port="25,465,993,995,465,143,110"]
...
[dovecot]

port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s
enabled = true
filter = dovecot
action = iptables-ipset-proto4[name=dovecot, port="25,465,993,995,465,143,110"]
...

Note: you need to define name in iptables-ipset-proto4[] to make it work properly
after Restart your fail2ban
# /etc/init.d/fail2ban restart
...
# /etc/init.d/fail2ban status
● fail2ban.service - Fail2Ban Service
   Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled)
   Active: active (running) since Thu 2016-10-06 12:10:29 WIB; 4min 24s ago
     Docs: man:fail2ban(1)
  Process: 24350 ExecStop=/usr/bin/fail2ban-client stop (code=exited, status=0/SUCCESS)
  Process: 24358 ExecStart=/usr/bin/fail2ban-client -x start (code=exited, status=0/SUCCESS)
 Main PID: 24361 (fail2ban-server)
   CGroup: /system.slice/fail2ban.service
           └─24361 /usr/bin/python3 /usr/bin/fail2ban-server -s /var/run/fail...

Oct 06 12:10:29 mars fail2ban-client[24358]: 2016-10-06 12:10:29,293 fail2ba...5
Oct 06 12:10:29 mars fail2ban-client[24358]: 2016-10-06 12:10:29,294 fail2ba...e
Oct 06 12:10:29 mars systemd[1]: Started Fail2Ban Service.
Hint: Some lines were ellipsized, use -l to show in full.
You can enable other fail2ban service such as apache, ftp, etc.
If you need to latest version of fail2ban, download and install it from source https://github.com/fail2ban/fail2ban and manually configure its service.
I add some regex filter here if you want to use.

References:

Wednesday, October 5, 2016

Simple Pagination With PHP and MySQL

This is my personal note to create simple pagination using php and mysql. I used mysqli object oriented style for future php support. Version MySQL and PHP are:
  • MySQL Version 5.5
  • PHP Version 5.6
To create your own demo, create your database and populate it.
CREATE TABLE `kci_logipv4` (
  `logdate` datetime DEFAULT NULL,
  `logipv4` int(11) unsigned DEFAULT NULL,
  `logmsg` varchar(1000) DEFAULT NULL,
  `logfrom` int(11) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `kci_logipv4` VALUES ('2016-09-28 23:22:11',3104583205,'SSH',1),('2016-09-28 23:22:11',3104583205,'SSH',1),('2016-09-29 09:07:50',1347119510,'SSH',1),('2016-09-29 09:07:51',1347119510,'SSH',1),('2016-09-29 20:28:27',3743330746,'SSH',1),('2016-09-29 20:28:28',3743330746,'SSH',1),('2016-09-29 20:59:51',1033072143,'SSH',1),('2016-09-29 20:59:53',1033072143,'SSH',1),('2016-09-29 21:06:55',1907273049,'SSH',1),('2016-09-29 21:06:57',1907273049,'SSH',1),('2016-09-30 03:20:08',3075559489,'SSH',1),('2016-09-30 03:20:09',3075559489,'SSH',1),('2016-09-30 11:47:19',1323303364,'SSH',1),('2016-09-30 11:47:21',1323303364,'SSH',1),('2016-09-30 21:59:33',3565240261,'SSH',1),('2016-09-30 21:59:35',3565240261,'SSH',1),('2016-10-01 03:09:18',1794631394,'SSH',1),('2016-10-01 03:09:18',1794631394,'SSH',1),('2016-10-01 10:02:35',2746017717,'SSH',1),('2016-10-01 10:02:36',2746017717,'SSH',1),('2016-10-01 10:29:18',1963359914,'SSH',1),('2016-10-01 10:29:19',1963359914,'SSH',1),('2016-10-01 10:57:30',2000423175,'SSH',1),('2016-10-01 10:57:31',2000423175,'SSH',1),('2016-10-01 21:33:06',1757971329,'SSH',1),('2016-10-01 21:33:07',1757971329,'SSH',1),('2016-10-02 21:00:31',1033072141,'SSH',1),('2016-10-02 21:00:34',1033072141,'SSH',1),('2016-10-03 02:35:10',2065638212,'SSH',1),('2016-10-03 02:35:11',2065638212,'SSH',1),('2016-10-03 06:18:41',3754290014,'SSH',1),('2016-10-03 06:18:43',3754290014,'SSH',1),('2016-10-03 15:14:53',1912501632,'SSH',1),('2016-10-03 15:14:53',1912501632,'SSH',1),('2016-10-04 00:04:44',3281659836,'SSH',1),('2016-10-04 00:04:45',3281659836,'SSH',1),('2016-10-04 01:45:32',1168426137,'SSH',1),('2016-10-04 01:45:33',1168426137,'SSH',1),('2016-10-04 12:04:05',2065638165,'SSH',1),('2016-10-04 12:04:05',2065638165,'SSH',1),('2016-10-04 13:11:16',457715326,'SSH',1),('2016-10-04 13:11:16',457715326,'SSH',1),('2016-10-04 16:50:40',1839072489,'SSH',1),('2016-10-04 16:50:40',1839072489,'SSH',1),('2016-10-05 09:20:48',1760484871,'',1),('2016-10-05 09:20:48',1760484871,'',1);
Here is the kci_logread.php code you can view it live
<?php

/*
database: database
table: kci_logipv4
logdate datetime
logipv4 int(11)
logmsg varchar(1000)
logfrom int
*/

// host, user, password, database, [port]
$mysqli = new mysqli("localhost", "user", "password", "database");
if ($mysqli->connect_errno) {
    die('Internal Server Error maybe database');
}

//This is the page number want to display
//retrieve from user navigation via method get or post
$page = 1;
if(isset($_GET["page"])){
    $page = intval($_GET["page"]); // sanitize input
}
if(isset($_POST["page"])){
    $page = intval($_POST["page"]); // sanitize input
}
//This is the number of results displayed per page
$page_rows = 15;

//count all result
//must equal to query to display data
$res = $mysqli->query("select Count(*) as total from kci_logipv4");
$rows = $res->num_rows;
//number of data available
$total=0;
if($rows) {
    $row = $res->fetch_assoc();
    $total = $row['total'];
}

//this is which first row should be retrieve
$start = ($page_rows * $page) - $page_rows;
//query to display data
//read $page_row data start from row $start 
$res = $mysqli->query("SELECT * FROM kci_logipv4 order by logdate desc Limit $start, $page_rows ");
//number of data to display
$rows = $res->num_rows;

//This tells us the page number of our last page
$last = ceil($total/$page_rows);

?>
<html>
<body>
<p>Server Farm Info</p>
<?php
if ($res) {
    echo "<p>Total: $total</p>";
    if ($rows>0) {
?>
<table border="1">
    <tr>
        <th>From</th>
        <th>Datetime</th>
        <th>IP</th>
        <th>Comment</th>
    </tr>
<?php
        while ($row = $res->fetch_assoc()) {
?>
    <tr>
        <td>Server farm <?php //echo $row['logfrom']; ?></td>
        <td><?php echo $row['logdate']; ?></td>
        <td align="center"><?php echo long2ip($row['logipv4']); ?></td>
        <td><?php echo $row['logmsg']; ?></td>
    </tr>
<?php
        }
    } else {
        echo "<p>No Data</p>";
    }
?>
</table>
<?php
    if ($last>1) {
        echo "<P>";
        if ($page>1) {
            echo "<a href=\"".htmlspecialchars($_SERVER["PHP_SELF"], ENT_QUOTES, "utf-8")."?page=1\">First</a> ";
        }
        if ($page>2 && $page<=$last) {
            echo "... ";
        }
        if ($page>1) {
            echo "<a href=\"".htmlspecialchars($_SERVER["PHP_SELF"], ENT_QUOTES, "utf-8")."?page=".($page-1)."\">".($page-1)."</a> ";
        }
        echo "$page ";
        if ($page+1<=$last) {
            echo "<a href=\"".htmlspecialchars($_SERVER["PHP_SELF"], ENT_QUOTES, "utf-8")."?page=".($page+1)."\">".($page+1)."</a> ";
        }
        if ($page+1<$last) {
            echo "... ";
        }
        if ($page<$last) {
            echo "<a href=\"".htmlspecialchars($_SERVER["PHP_SELF"], ENT_QUOTES, "utf-8")."?page=$last\">Last</a> ";
        }
        echo "| Number of pages: $last </p>";
} else {
    echo "<p>Query Fail</p>";
}
?>
</body>
</html>

Tuesday, October 4, 2016

Odoo 9: restore using curl

Additional requirement:

  • zip & unzip
  • curl

Install additional requirement

# apt-get install zip unzip curl

To restore Odoo 9 via web front end using curl, you need to parse 4 parameters, they are:

  • master password: master_pwd
  • name: name
  • backup file (in zip): backup_file
  • restore option (copy or move): copy=true

Regarding to web front end we can use copy option for almost restoring Odoo 9.

In order to avoid conflicts between databases, Odoo needs to know if this database was moved or copied. If you don't know, answer "This database is a copy".

Here is the command to restore Odoo 9 via web front end using curl:

$ curl -F 'master_pwd=password' -F backup_file=@/home/user/test.zip -F 'copy=true' -F 'name=dbname' http://localhost:8069/web/database/restore
You can automate restore your Odoo 9 in backup site using cron. For back up, please refer to backup procedure.

References:

Monday, October 3, 2016

Fail2ban: install dependency python library in Debian Jessie

These are some python library that may be used in Fail2ban:

  • pyinotify >= 0.8.3 (Linux >= 2.6.13)
  • gamin >= 0.0.21
  • systemd >= 204
  • dnspython
These are my /etc/apt/sources.list:
deb http://kambing.ui.ac.id/debian/ jessie main
deb-src http://kambing.ui.ac.id/debian/ jessie main
deb http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main
#backport
deb http://ftp.debian.org/debian jessie-backports main

Install them all:

# apt-get install gamin systemd python-pyinotify python-dnspython python3-pyinotify

References: