<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>UNIX &#8211; Johnny Morano&#039;s Tech Articles</title>
	<atom:link href="https://jmorano.moretrix.com/tag/unix/feed/" rel="self" type="application/rss+xml" />
	<link>https://jmorano.moretrix.com</link>
	<description>Ramblings of an old-fashioned space cowboy</description>
	<lastBuildDate>Sat, 09 Apr 2022 07:11:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>

<image>
	<url>https://jmorano.moretrix.com/wp-content/uploads/2022/04/cropped-jmorano_emblem-32x32.png</url>
	<title>UNIX &#8211; Johnny Morano&#039;s Tech Articles</title>
	<link>https://jmorano.moretrix.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Time based network access control on OpenBSD</title>
		<link>https://jmorano.moretrix.com/2022/03/time-based-network-access-control-on-openbsd/</link>
					<comments>https://jmorano.moretrix.com/2022/03/time-based-network-access-control-on-openbsd/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Tue, 01 Mar 2022 13:14:17 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[OpenBSD]]></category>
		<category><![CDATA[PF]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">https://jmorano.moretrix.com/?p=1293</guid>

					<description><![CDATA[Time based ACL (access control lists) features do not exist in BSD&#8217;s packet filter (PF). Having your network&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Time based ACL (access control lists) features do not exist in BSD&#8217;s packet filter (<code>PF</code>). Having your network &#8220;shut down&#8221; at certain times (for instance, allow certain network ranges or specific IP addresses only during &#8220;business hours&#8221; or a specific time range), can be achieved with a simple <code>PF</code> table and a <code>cronjob</code>.</p>



<p>First, let&#8217;s set up the <code>PF</code> table which will control the traffic. Add the following to your <code>/etc/pf.conf</code> :</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># add time block table
table &lt;time_block> { } persist
</pre>



<p>Next, create a <code>PF</code> rule which block traffic for all entries in the <code>time_block</code> table:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># block all CIDR addresses in the time block table
block in quick log from &lt;time_block> to any
</pre>



<p>Since the <code>time_block</code> table is still empty, no traffic is actually blocked.</p>



<p>The last thing to implement, is periodically manipulating the <code>time_block</code> table. This could be done by creating two <code>cronjobs</code>:</p>



<ol class="wp-block-list"><li>allow traffic at the beginning of &#8220;business hours&#8221;</li><li>block traffic at the end of &#8220;business hours&#8221;</li></ol>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">crontab -e
# Allow traffic
0 7 * * * /usr/local/scripts/allow_employees.sh > /dev/null 2>&amp;1
# Block traffic
0 17 * * * /usr/local/scripts/block_employees.sh > /dev/null 2>&amp;1
﻿</pre>



<p>The <code>allow_employees.sh</code> script will allow certain network ranges by ensuring those are removed from the <code>time_block</code> table:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/bin/sh

/sbin/pfctl -Td -t time_block 10.1.0.0/24
/sbin/pfctl -Td -t time_block 10.2.0.0/24
</pre>



<p>The <code>block_employees.sh</code> script will do the exact opposite: it will add ranges to the <code>time_block</code> table so that their network access will be blocked by the firewall:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/bin/sh

/sbin/pfctl -Ta -t time_block 10.1.0.0/24
/sbin/pfctl -Ta -t time_block 10.2.0.0/24
</pre>



<p>Finally deploy your new PF rules (first test them!)</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">pfctl -nf /etc/pf.conf
pfctl -f /etc/pf.conf</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2022/03/time-based-network-access-control-on-openbsd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Block countries on OpenBSD using pf</title>
		<link>https://jmorano.moretrix.com/2022/03/block-countries-on-openbsd-using-pf/</link>
					<comments>https://jmorano.moretrix.com/2022/03/block-countries-on-openbsd-using-pf/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Tue, 01 Mar 2022 12:28:09 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[OpenBSD]]></category>
		<category><![CDATA[PF]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">https://jmorano.moretrix.com/?p=1291</guid>

					<description><![CDATA[Same as in the previous article, full countries can be easily blocked on OpenBSD firewall using the pf&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Same as in the <a href="https://jmorano.moretrix.com/2022/03/block-countries-using-iptables/" data-type="post" data-id="1285">previous article</a>, full countries can be easily blocked on OpenBSD firewall using the <code>pf</code> command and <a rel="noreferrer noopener" href="https://ipdeny.com/" target="_blank">https://ipdeny.com/</a>.</p>



<p>The zone files provided by <a rel="noreferrer noopener" href="https://ipdeny.com/" target="_blank">https://ipdeny.com/</a> need to be stored locally. A simple way to achieve this is by having a <code>cronjob</code> downloading those periodically (for instance once per day):</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/bin/sh

# download the latest country zone files
curl -s https://www.ipdeny.com/ipblocks/data/countries/ru.zone > /etc/ru.zone
curl -s https://www.ipdeny.com/ipblocks/data/countries/cn.zone > /etc/cn.zone
﻿</pre>



<p>We store them directly to <code>/etc</code> in the above example.</p>



<p>In the <code>/etc/pf.conf</code>, first add a table based on the files you have generated with the above statements:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># add a bad hosts table based on local disk text files
# one CIDR per line
table &lt;badhosts> persist file "/etc/ru.zone" file "/etc/cn.zone"
</pre>



<p>In the above example, we have created a table called <code>badhosts</code> based on two local files.</p>



<p>Finally we need some rules which actually blocks from and to these network ranges, an example <code>PF</code> block rule could be:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># block bad IP addresses
block from &lt;badhosts> to any
block from any to &lt;badhosts>
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2022/03/block-countries-on-openbsd-using-pf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Secure MySQL Backups with GnuPG</title>
		<link>https://jmorano.moretrix.com/2012/08/secure-mysql-backups-gnupg/</link>
					<comments>https://jmorano.moretrix.com/2012/08/secure-mysql-backups-gnupg/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Thu, 09 Aug 2012 12:03:13 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[GPG]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PGP]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=871</guid>

					<description><![CDATA[One way to secure your MySQL backups, is to encrypt the backup file using PGP/GnuPG. Of course you&#8230;]]></description>
										<content:encoded><![CDATA[<p>One way to secure your MySQL backups, is to encrypt the backup file using PGP/GnuPG. Of course you will need to own a PGP/GnuPG private key, which can be easily created using the PGP/GnuPG tools.</p>
<p>On a Debian/Ubuntu Linux host, install the &#8216;gnupg&#8217; package.</p>
<pre class="brush:shell">
# apt-get install gnupg
</pre>
<p>After installation, generate a PGP/GnuPG key using the &#8216;gpg&#8217; command and go through the questions:</p>
<pre class="brush:shell">
# gpg --gen-key
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection?
*snip*
</pre>
<p>Once your key has been generated, you are ready to start using it.</p>
<p>In this example, MySQL backups will be created using the &#8216;mysqldump&#8217; command. The output of that command will be compressed using &#8216;gzip&#8217;, since the &#8216;mysqldump&#8217; generates plain text output.</p>
<p>The &#8216;gpg&#8217; command takes two arguments:</p>
<ol>
<li>&#8211;encrypt : to define that we will encrypting the output coming STDOUT</li>
<li>-r user@domain.com : this parameter defines the key that will be used for the encryption</li>
</ol>
<p>When we put all these commands together:</p>
<pre class="brush:shell">

$ mysqldump --all-databases -uroot -psecret \
 | gzip - \
 | gpg --encrypt -r user@domain.com >mysql_dump_sql.bkp

</pre>
<p>The above example could be used in a cronjob to have daily backups.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2012/08/secure-mysql-backups-gnupg/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Finder and Samba share support</title>
		<link>https://jmorano.moretrix.com/2011/07/finder-samba-share-support/</link>
					<comments>https://jmorano.moretrix.com/2011/07/finder-samba-share-support/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Tue, 26 Jul 2011 13:22:30 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=658</guid>

					<description><![CDATA[I&#8217;ve answered a question on StackOverflow (actually on SuperUser) regarding Finder and Samba shares on Ubuntu Linux. It&#8217;s&#8230;]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve answered a question on StackOverflow (actually on SuperUser) regarding Finder and Samba shares on Ubuntu Linux. It&#8217;s only Ubuntu which has this problem, Finder works perfect with Samba when that Samba is installed on Debian, CentOS, &#8230;</p>
<p><a href="https://jmorano.moretrix.com/go/adfadfweradf/" title="Finder and Samba Shares" target="_blank">http://superuser.com/questions/283863/force-finder-to-log-in-as-guest-to-a-smb-share/300382#300382</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/07/finder-samba-share-support/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bash and the Screen</title>
		<link>https://jmorano.moretrix.com/2011/03/bash-and-the-screen/</link>
					<comments>https://jmorano.moretrix.com/2011/03/bash-and-the-screen/#comments</comments>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Tue, 08 Mar 2011 13:17:03 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Screen]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=522</guid>

					<description><![CDATA[Beauty and the Beast When working in a UNIX/Linux/MacOSX environment, the command is often used to execute some&#8230;]]></description>
										<content:encoded><![CDATA[<h3>Beauty and the Beast</h3>
<p>When working in a UNIX/Linux/MacOSX environment, the command is often used to execute some tasks. The default shell in the <a href="http://en.wikipedia.org/wiki/Apple_Terminal">Terminal.app</a> (MacOSX) and in most other terminals, is the <a href="http://www.gnu.org/software/bash/">Bourne Again Shell</a> aka bash.</p>
<p>Bash is intended to be a conformant implementation of the Shell and Utilities portion of the IEEE POSIX specification. Bash also incorporates useful features from the Korn and C shells (ksh and csh).</p>
<p><a href="http://www.gnu.org/software/screen/">Screen</a> is a full-screen text-based window manager with VT100/ANSI terminal emulation. It has the ability to detach shell sessions, which is extremely useful for executing remote processes or executing processes that should be terminated after log out or termination of the shell process itself.<br />
<span id="more-522"></span></p>
<h3>my ~/.bashrc</h3>
<p>First we start off with configuration the Bash configuration file, which is located at ~/.bashrc for the current user or at /etc/bashrc.bashrc for system-wide configurations. </p>
<p>Most users will just edit their own bashrc file.<br />
The options defined in this file, have comments above them so I won&#8217;t re-explain them.</p>
<pre class="brush:bash">
# define your local timezone
export TZ='Europe/Brussels'

# If not running interactively, don't do anything
[ -z "$PS1" ] &amp;&amp; return

# don't put duplicate lines in the history. See bash(1) for more options
export HISTCONTROL=ignoredups
# ... and ignore same sucessive entries.
export HISTCONTROL=ignoreboth

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] &amp;&amp; eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] &amp;&amp; [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# define all aliases in a separate file
if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# turn on bash completion, must be installed separately
if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

# define some colors which will be used in PS1 and PS2
BLUE="[�33[0;34m]"
LIGHT_GRAY="[�33[0;37m]"
GREEN="[�33[0;32m]"
LIGHT_BLUE="[�33[1;34m]"
LIGHT_CYAN="[�33[1;36m]"
YELLOW="[�33[1;33m]"
WHITE="[�33[1;37m]"
RED="[�33[0;31m]"
NO_COLOUR="[�33[0m]"

# if this shell was started in the screen command, use a different PS1 prompt
if [[ $TERM =~ screen ]] ; then
    PS1="${GREEN}.oO( $BLUEh $GREEN|$BLUE w $GREEN)Oo"'[�33k][�33\]'".$NO_COLOUR "
else
    PS1="${GREEN}.oO( $BLUEh $GREEN|$BLUE w $GREEN)Oo.$NO_COLOUR "
fi
PS2="$GREEN.oO($NO_COLOUR "</pre>
<p>This local bashrc file enables some default settings and creates a fancy bash prompt in colour. (See screenshot)</p>
<p><img decoding="async" src="https://jmorano.moretrix.com/wp-content/uploads/2011/03/Screenshot-insaniac@musashi.moretrix.com-home-insaniac-1.png" alt="Screen Shell Prompt" /></p>
<p>Next we&#8217;ll set up the Screen configuration file.</p>
<h3>my ~/.screenrc</h3>
<p>The following Screen configuration file sets some options that I find useful. These options included:</p>
<ul>
<li>no splash screen at startup</li>
<li>no visual bell</li>
<li>a customized status bar at the bottom of the screen</li>
<li>a huge scrollback buffer</li>
<li>updated window names, based on the current command</li>
<li>UTF8 encoding</li>
</ul>
<p>The file will be saved in the user home directory, at ~/.screenrc</p>
<pre class="brush:bash">
# some default settings
startup_message off
vbell off
msgwait 1
defutf8 on
compacthist on

# Monitor windows
defmonitor on
activity ""

# Turns off alternate screen switching in xterms,
# so that text in screen will go into the xterm's scrollback buffer:
termcapinfo xterm* ti@:te@
altscreen on

# Enable 256 color terminal
attrcolor b ".I"
termcapinfo xterm 'Co#256:AB=E[48;5;%dm:AF=E[38;5;%dm'
defbce "on"

# Log 10000 lines
defscrollback 50000

backtick 2 60 60 echo $USERNAME

screen 0

shelltitle '. |bash'
hardstatus alwayslastline '%{= .y}.oO(%{= .b}%2`@%H%{= .y})Oo. %{= .b}%{+} %= %-w %{= .yb} %n:[%t] %{= db} %+w %{= .y}time: [%c]'

bindkey -k k2 screen                                    # F2  | Create new window
bindkey -k k3 prev                                      # F3  | Previous Window
bindkey -k k4 next                                      # F4  | Next Window
register r "^a:source $HOME/.screenrc^M"                #     | Goes with F5 definition
bindkey -k k5 process r                                 # F5  | Reload profile
bindkey -k k6 detach                                    # F6  | Detach from this session
bindkey -k k7 copy                                      # F7  | Enter copy/scrollback mode
register t "^aA^aa^k^h"                                 #     | Goes with the F8 definition
bindkey -k k8 process t                                 # F8  | Re-title a window
</pre>
<p>In order to have updated window names, it is important that the above Bash configuration regarding the PS1 variable, has been enabled. If not, then there will be no updated window names!</p>
<p>This configuration file was used to create the following screenshot:<br />
<img decoding="async" src="https://jmorano.moretrix.com/wp-content/uploads/2011/03/Screenshot-johnny@ubuntu-sunray1-Dev-Elop.png" alt="Screenshot Screen with 3 open windows" /></p>
<h3>References</h3>
<p>Some options were taken out of the <a href="https://launchpad.net/byobu">Byobu</a> configuration file, others were found on the <a href="http://www.google.com/">Interweb</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/03/bash-and-the-screen/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>IPtables Firewall Script</title>
		<link>https://jmorano.moretrix.com/2010/10/iptables-firewall-script/</link>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Mon, 18 Oct 2010 13:29:49 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[IPTables]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=397</guid>

					<description><![CDATA[Some years ago, I had been searching the Internet quite a lot for a descent and simple firewall&#8230;]]></description>
										<content:encoded><![CDATA[<p>Some years ago, I had been searching the Internet quite a lot for a descent and simple firewall script. I wanted maximum security and less as possible complexity. Most of the scripts back then, were made for huge network environments or for DSL users. None of them seemed to cover the simple server protection through IPtables.</p>
<p>So I started gathering information, reading articles and fiddling my own IPtables firewall script.<br />
<span id="more-397"></span><br />
Eventually over the years, the script quite big and is still easy to maintain.</p>
<p>The script itself has quite a lot of comments and should explain itself.</p>
<pre class="brush:shell">
#!/bin/bash
### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# X-Interactive:     true
# Short-Description: Start/stop firewall script from hell
### END INIT INFO


# Description: Simple firewall script
# Author: Johnny Morano <insaniac@moretrix.com>
# Version: 0.04
# Usage:
#    ./firewall.sh 


#---------#
# History #
#---------#
 
# 0.01 .... Initial release, based on http://iptables-tutorial.frozentux.net/iptables-tutorial.html
# 0.02 .... Added more security by reading http://www.brandonhutchinson.com/iptables_fw.html
# 0.03 .... Added even more shit thanks to http://danieldegraaf.afraid.org/info/iptables/examples
# 0.04 .... Using ULOGD now for traffic accounting (inspired by http://tumbleweed.org.za/2008/04/02/bandwidth-accounting-ulogd)
# 0.05 .... Loading modules through modprobe

#---------------#
# Configuration #
#---------------#

IPTABLES=/sbin/iptables
SYSCTL=/sbin/sysctl
MODPROBE=/sbin/modprobe

#----------------#
# Initialization #
#----------------#

echo 
echo "    #---------------------------#"
echo "    # Firewall Script From Hell #"
echo "    #---------------------------#"
echo "                 by Johnny Morano"
echo

#
# Module loading
#
echo "Preload IP-Tables modules..."
$MODPROBE ip_tables
$MODPROBE iptable_nat
$MODPROBE iptable_mangle
$MODPROBE iptable_filter
$MODPROBE ipt_REJECT
$MODPROBE ipt_ULOG
$MODPROBE nf_nat
$MODPROBE nf_conntrack
$MODPROBE nf_conntrack_ipv4
$MODPROBE nf_conntrack_ftp

#
# Drop ICMP echo-request messages sent to broadcast or multicast addresses
#
echo "Enable network security settings..."
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

#
# Drop source routed packets
#
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route

#
# Enable TCP SYN cookie protection from SYN floods
#
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

#
# Don't accept ICMP redirect messages
#
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects

#
# Don't send ICMP redirect messages
#
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects

#
# Enable source address spoofing protection
#
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter

#
# Log packets with impossible source addresses
#
echo 1 > /proc/sys/net/ipv4/conf/all/log_martians

#
# Disable some ICMP settings that can be insecure
# Some of these were already disabled by the above echo statements
#
echo "Disable some ICMP settings..."
$SYSCTL -q -w net.ipv4.icmp_ignore_bogus_error_responses=1
$SYSCTL -q -w net.ipv4.icmp_echo_ignore_all=0
$SYSCTL -q -w net.ipv4.icmp_echo_ignore_broadcasts=1
$SYSCTL -q -w net.ipv4.icmp_ratelimit=1000

echo "Enable some extra network security..."
$SYSCTL -q -w net.ipv4.conf.all.accept_redirects=0
$SYSCTL -q -w net.ipv4.conf.all.accept_source_route=0
$SYSCTL -q -w net.ipv4.conf.all.rp_filter=1
$SYSCTL -q -w net.ipv4.conf.all.log_martians=1
$SYSCTL -q -w net.netfilter.nf_conntrack_acct=1

#
# Prevent SYN flood
#
$SYSCTL -q -w net.ipv4.tcp_syncookies=1

#
# Don't accept TCP connections unless we were here for their establishment
#
if [ -e /proc/sys/net/netfilter/ ]; then
        $SYSCTL -q -w net.netfilter.nf_conntrack_tcp_loose=1
else
        $SYSCTL -q -w net.ipv4.ip_conntrack_tcp_loose=1
fi
 
#
# Create policies and flush chains, then delete rules
#
echo "Creating default policies..."
$IPTABLES -P INPUT ACCEPT  
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD DROP  

echo "Flushing and deleting chains..."
for type in filter mangle nat; do
        echo "- Flushing, deleting and zeroing chains for $type"
        $IPTABLES -t $type -F
        $IPTABLES -t $type -X
        $IPTABLES -t $type -Z
done

# 
# Accounting stuff
#
echo "Creating accounting chains"
$IPTABLES -t mangle -N incoming
$IPTABLES -t mangle -N outgoing
$IPTABLES -t mangle -F incoming
$IPTABLES -t mangle -F outgoing

#$IPTABLES -t mangle -A incoming -p tcp --dport 80  -m comment --comment  "Incoming http TCP connections"
#$IPTABLES -t mangle -A incoming -p tcp --dport 443 -m comment --comment  "Incoming http/ssl TCP connections"
#$IPTABLES -t mangle -A incoming -p tcp --dport 22  -m comment --comment  "Incoming ssh TCP connections"
#$IPTABLES -t mangle -A incoming -p tcp --dport 21  -m comment --comment  "Incoming ftp TCP connections"
#$IPTABLES -t mangle -A incoming -p tcp --dport 25  -m comment --comment  "Incoming smtp TCP connections"
$IPTABLES -t mangle -A incoming -p tcp -m comment --comment  "Incoming TCP connections"

$IPTABLES -t mangle -A incoming -p udp -m comment --comment  "Incoming UDP connections"
$IPTABLES -t mangle -A incoming -p icmp -m comment --comment "Incoming ICMP connections"

$IPTABLES -t mangle -A outgoing -p tcp -m comment --comment  "Outgoing TCP connections"
$IPTABLES -t mangle -A outgoing -p udp -m comment --comment  "Outgoing UDP connections"
$IPTABLES -t mangle -A outgoing -p icmp -m comment --comment "Outgoing ICMP connections"

echo "Adding accounting to PRE- and POSTROUTING"
$IPTABLES -t mangle -A PREROUTING -i eth0 -j incoming
$IPTABLES -t mangle -A POSTROUTING -o eth0 -j outgoing

#
# Create a LOGDROP chain to log and drop packets
#
echo "Creating LOGDROP chain..."
$IPTABLES -N LOGDROP
$IPTABLES -F LOGDROP
#$IPTABLES -A LOGDROP -j LOG --log-prefix "firewall dropped packet: " --log-tcp-options --log-ip-options --log-uid -m limit --limit 2/sec
$IPTABLES -A LOGDROP -j ULOG --ulog-prefix "FIREWALL DROPPED" --ulog-nlgroup 1
$IPTABLES -A LOGDROP -p tcp -j REJECT --reject-with tcp-reset -m comment --comment "Reject TCP connections with tcp-reset"
$IPTABLES -A LOGDROP -p udp -j REJECT --reject-with icmp-port-unreachable -m comment --comment "Reject UDP connections with icmp-port-unreachable"
$IPTABLES -A LOGDROP -j DROP

#
# Create TCP_CHAIN chain
#
for CHAIN in TCP_CHAIN BAD_TCP TCP_SLOWLORIS ICMP_CHAIN UDP_CHAIN ; do
        echo "Creating chain $CHAIN..."
        $IPTABLES -N $CHAIN
        $IPTABLES -F $CHAIN
done

#----------------#
# Firewall rules #
#----------------#
#

#
# allow localhost services
#
echo "Accept localhost connections..."
$IPTABLES -A INPUT -i lo -s 0/0 -d 0/0 -j ACCEPT
$IPTABLES -A OUTPUT -o lo -s 0/0 -d 0/0 -j ACCEPT

#
#
# Allow network connections which have already been established (started by host) and related to your connection.
# FTP requires this as it may use various ports in support of the file transfer.)
#
echo "Set up established state..."
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow established incoming connections"
$IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow established outgoing connections"

#
# Block Fragments
#
echo "Drop Fragments on INPUT"
$IPTABLES -A INPUT -f -j LOGDROP -m comment --comment "Fragments Packets"

#
# Block bad TCP stuff
#
echo "Drop bad TCP packets (portscans, spoofing, ...)"
$IPTABLES -A BAD_TCP -p tcp ! --syn -m state --state NEW -j LOGDROP -m comment  --comment "Drop Sync"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL ALL -j LOGDROP -m comment           --comment "XMAS Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL NONE -j LOGDROP  -m comment         --comment  "NULL Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOGDROP -m comment --comment "Merry XMAS Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL FIN,URG,PSH -j LOGDROP -m comment   --comment "NMAP XMAS Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL PSH,ACK -m state --state RELATED -j LOGDROP -m comment --comment "Drop ALL PSH,ACK state RELATED"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL SYN,ACK,PSH -j LOGDROP -m comment   --comment "Drop ALL SYN,ACK,PSH"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ALL SYN,PSH -j LOGDROP -m comment       --comment "Drop ALL SYN,PSH"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags SYN,RST SYN,RST -j LOGDROP -m comment   --comment "SYN/RST Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags RST,FIN RST,FIN -j LOGDROP -m comment   --comment "RST/FIN Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags SYN,URG SYN,URG -j LOGDROP -m comment   --comment "SYN/URG Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset -m comment --comment "SYN/ACK Attack"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOGDROP  -m comment  --comment  "SYN/FIN Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags SYN,ACK NONE -j LOGDROP -m comment      --comment "Drop SYN,ACK NONE"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ACK,FIN FIN -j LOGDROP -m comment       --comment "Drop ACK,FIN FIN"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ACK,PSH PSH -j LOGDROP -m comment       --comment "Drop ACK,PSH PSH"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags ACK,URG URG -j LOGDROP -m comment       --comment "Drop ACK,URG URG"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags FIN,ACK FIN -j LOGDROP  -m comment      --comment  "Fin Packets Scan"
$IPTABLES -A BAD_TCP -p tcp --tcp-flags FIN,RST FIN,RST -j LOGDROP -m comment   --comment "Drop FIN,RST FIN,RST"

#
# Add BAD_TCP chain as 1st rule to TCP_CHAIN
# 
$IPTABLES -A TCP_CHAIN -j BAD_TCP
 
# ICMP rules
# Allow ping and traceroute
#
echo "Allow ping and traceroute..."
$IPTABLES -A ICMP_CHAIN -p icmp -s 0/0 --icmp-type 8 -j ACCEPT -m comment --comment "Allow ICMP ping"
$IPTABLES -A ICMP_CHAIN -p icmp -s 0/0 --icmp-type 11 -j ACCEPT -m comment --comment "Allow ICMP traceroute"


##
## Disable port-scans (part 1)
## 
#echo "Disable portscans..."
#$IPTABLES -A INPUT -m recent --update --hitcount 16 --name portscanblock --seconds 3600 -j LOGDROP
#$IPTABLES -A INPUT -m recent --name portscanblock --set -m tcp -p tcp --tcp-flags ! SYN,RST,ACK,FIN SYN -j LOGDROP

#
# Prevents more than 2 SSH connections per minute, to slow down SSH scans
# Allow connections to SSH server, but only allow 2 connections from one IP
#
echo "Allow only 2 SSH connections /minute and not more than 4 connections in total..."
$IPTABLES -A TCP_CHAIN -p tcp -m tcp --dport 22 -m recent --update --hitcount 2 --seconds 60 --name sshsin -j LOGDROP -m comment --comment "Drop SSH connection if more than 2 in 60 secs"
$IPTABLES -A TCP_CHAIN -p tcp --syn --dport 22 -m connlimit --connlimit-mask 32 --connlimit-above 4 -j LOGDROP -m comment --comment "Don't allow more than 4 connections"
$IPTABLES -A TCP_CHAIN -p tcp -m tcp --syn --dport 22 -m recent --set --name sshsin -j ACCEPT -m comment --comment "Allow TCP connections to ssh"

#
# Allow traffic to webserver
#
echo "Allow web traffic..."
# Small defense against slowloris
$IPTABLES -A TCP_CHAIN -p tcp --dport 80 -m connlimit --connlimit-above 20 --connlimit-mask 32 -j LOGDROP -m comment --comment "Allow only 20 connections per IP to port 80"
# This chain will be provisioned from /root/bin/block_slowloris_attacks.sh
$IPTABLES -A TCP_CHAIN -p tcp --dport 80 -j TCP_SLOWLORIS

$IPTABLES -A TCP_CHAIN -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow TCP connections to http"
$IPTABLES -A TCP_CHAIN -p tcp --dport 443 -j ACCEPT -m comment --comment "Allow TCP connections to https"

#$IPTABLES -A TCP_CHAIN -p tcp --dport 6000 -j ACCEPT -m comment --comment "Allow TCP connections to X11"
#$IPTABLES -A TCP_CHAIN -p udp --dport 6000 -j ACCEPT -m comment --comment "Allow UDP connections to X11"

#
# Allow traffic to mail platform
#
echo "Allow mail traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport  25 -j ACCEPT -m comment --comment "Allow TCP connections to smtp"
$IPTABLES -A TCP_CHAIN -p tcp --dport 110 -j ACCEPT -m comment --comment "Allow TCP connections to pop3"
$IPTABLES -A TCP_CHAIN -p tcp --dport 143 -j ACCEPT -m comment --comment "Allow TCP connections to imap"
$IPTABLES -A TCP_CHAIN -p tcp --dport 465 -j ACCEPT -m comment --comment "Allow TCP connections to smtps"
$IPTABLES -A TCP_CHAIN -p tcp --dport 993 -j ACCEPT -m comment --comment "Allow TCP connections to imaps"
$IPTABLES -A TCP_CHAIN -p tcp --dport 995 -j ACCEPT -m comment --comment "Allow TCP connections to pop3s"

#
# Allow traffic to FTP server
#
echo "Allow FTP traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport 20 -j ACCEPT -m comment --comment "Allow TCP connections to ftp-data"
$IPTABLES -A TCP_CHAIN -p tcp --dport 21 -j ACCEPT -m comment --comment "Allow TCP connections to ftp"
$IPTABLES -A TCP_CHAIN -p tcp --dport 989 -j ACCEPT -m comment --comment "Allow TCP connections to ftps-data"
$IPTABLES -A TCP_CHAIN -p tcp --dport 990 -j ACCEPT -m comment --comment "Allow TCP connections to ftps"
$IPTABLES -A TCP_CHAIN -p tcp --dport 115 -j ACCEPT -m comment --comment "Allow TCP connections to sftp"
$IPTABLES -A INPUT -m helper --helper ftp -j ACCEPT


#
# Allow traffic to DNS server
#
echo "Allow FTP traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport 53 -j ACCEPT -m comment --comment "Allow TCP connections to dns"
$IPTABLES -A UDP_CHAIN -p udp --dport 53 -j ACCEPT -m comment --comment "Allow UDP connections to dns"

#
# Allow traffic to database server (needed for replication)
#
echo "Allow MYSQL traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport 3306 -s 88.198.65.228 -j ACCEPT -m comment --comment "Allow TCP connections to mysql"
$IPTABLES -A UDP_CHAIN -p udp --dport 3306 -s 88.198.65.228 -j ACCEPT -m comment --comment "Allow UDP connections to mysql"

#
# Allow traffic to NTP server
#
echo "Allow NTP traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport 123 -j ACCEPT -m comment --comment "Allow TCP connections to ntp"
$IPTABLES -A UDP_CHAIN -p udp --dport 123 -j ACCEPT -m comment --comment "Allow UDP connections to ntp"

#
# Allow traffic to torrent
#
echo "Allow torrent traffic..."
$IPTABLES -A TCP_CHAIN -p tcp --dport 6959 -j ACCEPT -m comment --comment "Allow TCP connections to torrent"
$IPTABLES -A UDP_CHAIN -p udp --dport 6959 -j ACCEPT -m comment --comment "Allow UDP connections to torrent"

#
# Allow traffic to DCC
#
echo "Allow DCC traffic..."
$IPTABLES -A UDP_CHAIN -p udp --dport 6277 -j ACCEPT -m comment --comment "Allow UDP connections to DCC"

#
# Needed for portscan block (part 2)
#
#$IPTABLES -A INPUT -m recent --set --name portscanblock

#
# Allow the ICMP_CHAIN, TCP_CHAIN and UDP_CHAIN chains on INPUT
# 
echo "Add ICMP_, TCP_ and UDP_CHAIN to INPUT..."
$IPTABLES -A INPUT -p icmp -j ICMP_CHAIN
$IPTABLES -A INPUT -p tcp  -j TCP_CHAIN
$IPTABLES -A INPUT -p udp  -j UDP_CHAIN

#
# debugging and logging
#
echo "Log and drop everything else..."
$IPTABLES -p ALL -A INPUT -j LOGDROP -m comment --comment "Drop all packets"
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A services watchdog written in Perl</title>
		<link>https://jmorano.moretrix.com/2010/10/a-services-watchdog-written-in-perl-2/</link>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Mon, 18 Oct 2010 12:12:18 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=390</guid>

					<description><![CDATA[This Perl script was initially written about 3 or 4 years ago, but still does its daily job:&#8230;]]></description>
										<content:encoded><![CDATA[<p>This Perl script was initially written about 3 or 4 years ago, but still does its daily job: monitor that certain processes are running and if not, restart them (plus send out a notification).</p>
<p>The script should run as the root user (since it will be restarting services or processes), and can easily be configured as a cron job.</p>
<p>Let&#8217;s say you&#8217;ve saved your script in <code>/root/bin/services_watchdog.pl</code>, then the cronjob could look like:</p>
<pre class="brush:shell">
# Check if main services are still running
*/5 * * * * /root/bin/services_watchdog.pl
</pre>
<p><span id="more-390"></span></p>
<p>This will check every 5 minutes if all required processes are running.</p>
<p>The script itself will start with:</p>
<pre class="brush:perl">
#!/usr/bin/perl
use strict; use warnings;
use Proc::ProcessTable;
</pre>
<p>The script uses <a href="http://search.cpan.org/~jwb/Proc-ProcessTable-0.50/ProcessTable.pm" title="Proc::ProcessTable" target="_blank">Proc::ProcessTable</a> to retrieve a full process list.<br />
The processes it should monitor, are easily defined in a hash:</p>
<pre class="brush:perl">
my %services_table = (
        'MySQL' => {
                'cmd' => '/etc/init.d/mysql restart',
                're' => '/usr/sbin/mysqld --basedir=/usr',
        },
        'Postfix' => {
                'cmd' => '/etc/init.d/postfix restart',
                're' => '/usr/lib/postfix/master',
        },
# ...
);
</pre>
<p>The actual processing of the process list can be done in a minumum of lines:</p>
<pre class="brush:perl">
my %nok_services = %services_table ;
my $services = join '|', map {$services_table{$_}->{'re'}} keys %services_table;

my $process_table = Proc::ProcessTable->new;

foreach my $process ( @{ $process_table->table } ) {
        if($process->cmndline =~ m/($services)/) {
                my $proc_name = (grep { $1 =~ m/Q$services_table{$_}->{'re'}E/} keys %services_table)[0];
                delete $nok_services{$proc_name}                                  if exists($nok_services{$proc_name});
                $services = join '|', map {$services_table{$_}->{'re'}}           keys %services_table;
        }
}
</pre>
<p>Finally, the script tries to restart the missing service and prints a log message:</p>
<pre class="brush:perl">
foreach my $process (keys %nok_services) {
        print "$process NOT running! Restarting...n";
        system($nok_services{$process}->{'cmd'});
        if ($? == -1) {
                print "failed to execute: $!n";
        }
        elsif ($? & 127) {
                printf "child died with signal %d, %s coredumpn", ($? & 127),  ($? & 128) ? 'with':'without';
        }
        else {
                printf "child exited with value %dn", $? >> 8;
        }
}
</pre>
<p>And that&#8217;s all folks!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Blacklist emails with DCC through a Perl script</title>
		<link>https://jmorano.moretrix.com/2010/10/blacklist-emails-with-dcc-through-a-perl-script/</link>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Fri, 08 Oct 2010 13:26:51 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=363</guid>

					<description><![CDATA[DCC is a wonderful tool, but it needs to be fed constantly. After going through the process of&#8230;]]></description>
										<content:encoded><![CDATA[<p>DCC is a wonderful tool, but it needs to be fed constantly.<br />
After going through the process of blacklisting a few emails that weren&#8217;t tag as spam, I found myself in a not so lazy position. We don&#8217;t like that &#8230; so we wrote a Perl script to kind of automate this process. (yes, we talk in plural since we are feeling quite majestic today)</p>
<p><span id="more-363"></span><br />
The process is actually fairly simple, and this should be practically the biggest reason to automate this process.<br />
DCC will create a text file for every email it checks (whether you like it or not), in /var/dcc/log. The bottom of those files contain variables and HEX values which are required to white- or blacklist messages in the DCC server.</p>
<p>Example of a text file generated by DCC (such the bottom actually):</p>
<pre class="brush:shell">
### end of message body ########################
unknown-->spam
dccifd  global-log  

X-DCC-musashi-Metrics: musashi.moretrix.com 32702; bulk Body=many Fuz1=many
        Fuz2=many
                            reported: 1 spam          checksum  server wlist
                       IP: e475b896 492c60fc efecb432 6e29e3c5
                 env_From: c339fff7 216652a7 36a8ffa4 692ca3c1
                     From: 21eadc86 d5fa588e 2de85418 e2e18829
          substitute helo: e34e261c 6c7e0450 454065a8 a19f7b6c          many
               Message-ID: 48f0f506 f391cb50 5c9a8033 ff5c6bbb
                 Received: 4683ff3f 121cf370 ffb45478 dad90632
                     Body: 9b8a1cda 67a889ba 5d78d440 3b27da17       1
                     Fuz1: 27c25f69 0894e8b9 b5efa920 959aef57       1
                     Fuz2: 84451221 40f95ad5 fe80b2ef a0d1e5fd       1
     substitute mail_host: 956f550f f8dadf7e 38637790 756f8240

result: reject
</pre>
<p>In most cases, black- or whitelist entries will be created based on the fields &#8216;Body&#8217;, &#8216;Fuz1&#8217; or &#8216;Fuz2&#8217; (or all three will be added), but it is also possible to create criteria based on &#8216;IP&#8217;, &#8216;From&#8217;, &#8230;</p>
<p>Quick Overview of the process:</p>
<ol>
<li>Locate the correct text file in /var/dcc/log</li>
<li>Grab the fields you want to white- or blacklist</li>
<li>prefix these fields with either &#8216;many hex&#8217; or &#8216;ok&#8217;</li>
<li>Add those fields to the corresponding file in /var/dcc</li>
</ol>
<p>In my case, I&#8217;ve created a file called /var/dcc/blacklist_spam which is included from /var/dcc/whiteclnt</p>
<p>The script goes as follows:</p>
<pre class="brush:perl">
#!/usr/bin/perl
use strict;
use warnings;

use Getopt::Long;

my $fields = 'Body,Fuz1,Fuz2';
my $result = GetOptions("fields=s", $fields);

my $criteria = @ARGV;

chdir '/var/dcc/log' or die "Kak: $!";
my @blacklist;
foreach my $crit (@{$criteria}){
        print "criteria: $critn";
        open my $grep, '-|', "grep -l '$crit' *" or die "Kak: $!";
        my @files = <$grep>;
        close $grep;

        foreach my $file (@files){
                $fields =~ s/,/|/g;
                open my $grep, '-|', "egrep '^ *($fields)' $file" or die "Kak: $!";
                my @hexes = <$grep>;
                close $grep;

                map { s/^s*/manythext/; s/((S+s*){7}).*/$1/; } @hexes;
                push @blacklist, @hexes
        }
}

open my $blacklist, '>>', '/var/dcc/blacklist_spam' or die "Kak: $!";
print {$blacklist} $_ foreach @blacklist;
close $blacklist;

print "Written " . scalar @blacklist . " to /var/dcc/blacklist_spamnn";
</pre>
<p>The criteria I use in order to search the emails is usually the Message-ID field, since this should be a unique identifier.</p>
<pre class="brush:shell">
# dcc_block 20101008111306.31259.876787136.swift@email.addemar.com
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Monitor resources on a UNIX machine (with Perl)</title>
		<link>https://jmorano.moretrix.com/2010/10/monitor-resources-on-a-unix-machine-with-perl/</link>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Thu, 07 Oct 2010 12:23:30 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[UNIX]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=351</guid>

					<description><![CDATA[To get an overview of what is running on a certain UNIX/Linux host, most users will usually run&#8230;]]></description>
										<content:encoded><![CDATA[<p>To get an overview of what is running on a certain UNIX/Linux host, most users will usually run of one the following commands:</p>
<ul>
<li>ps</li>
<li>top</li>
<li>htop</li>
</ul>
<p>But most of the times, they will not give a correct view of what is really going on, and most of the times we want to see totals instead of individual processes with their resource consumption.</p>
<p><span id="more-351"></span><br />
Since Perl is one of the default scripting languages on almost every UNIX/Linux flavour, we will use this language to create a script which will allow us to get general overview of how much an application is really using up (all childs processes, threads, &#8230;).</p>
<p>The script uses two functions:</p>
<ul>
<li>get_proc_list()</li>
<li>print_sorted()</li>
</ul>
<pre class="brush:perl">
sub get_proc_list {
    my($ps_fields, $key) = @_;

    my $ps_cmd = "ps -T -e -o $ps_fields,$DEFAULT_FIELDS --sort $ps_fields";
    my @process_list = do {
        open my $cmd, '-|', $ps_cmd or die "Kak: $!n";
        <$cmd>;
    };

    my %top_res;
    foreach my $cmd (@process_list[1.. $#process_list]){
        $cmd =~ s/^s*//;
        $cmd =~ s/s*$//;
        my(@fields) = split /s+/, $cmd;

        $top_res{"$fields[-1]_$fields[-2]"}->{ "${ps_fields}_sum" } += $fields[0];
    }

    my @sorted_keys = sort { 
            $top_res{$b}->{"${ps_fields}_sum"} <=> $top_res{$a}->{"${ps_fields}_sum"} 
        } 
        keys %top_res;

    return (%top_res, @sorted_keys, "${ps_fields}_sum");
}
</pre>
<p>This function executes the <code>ps</code> command and will create a sum of the resource values per application and user. These values will be sorted in a descended way (highest will be first element in the list).</p>
<pre class="brush:perl">
sub print_sorted {
    my($data, $sorted_keys, $sum_key, $limit) = @_;

    $limit ||= $#{$sorted_keys};

    my ($title) = ($sum_key =~ m/(.*?)_sum$/);

    print "====================[ TOP $limit OF $title ]======================n";
    foreach my $key ( @$sorted_keys[0..$limit] ) {
        my ($app, $user) = ( $key =~ /(.*?)_([^_]+)$/ );
    
        printf "%9.2ft%16st%16sn", $data->{$key}->{$sum_key}, $app, $user;
    }
    print "="x60, "nn";

}
</pre>
<p>This function will print out the data structures returned by <code>get_proc_list()</code>.</p>
<p>We call these functions in one liner statements like:</p>
<pre class="brush:perl">
print_sorted( get_proc_list('pcpu'), 20 );
print_sorted( get_proc_list('pmem'), 20 );
print_sorted( get_proc_list('rss'), 10 );
</pre>
<p>Sample output:</p>
<pre class="brush:shell">
====================[ TOP 5 OF pcpu ]======================
     5.50	     firefox-bin	         dieterw
     2.90	          chrome	            phil
     2.60	            java	            dave
     2.50	 plugin-containe	             rob
     2.50	     firefox-bin	            dave
     2.40	     firefox-bin	             rob
============================================================

====================[ TOP 5 OF pmem ]======================
   375.10	            java	            dave
   346.00	            java	           fredv
    49.00	     firefox-bin	           fredv
    40.30	            java	         dieterw
    28.00	             exe	            phil
    19.20	 console-kit-dae	            root
============================================================

====================[ TOP 3 OF rss ]======================
123533296.00	            java	            dave
117568200.00	            java	           fredv
16021180.00	     firefox-bin	           fredv
14749020.00	            java	         dieterw
============================================================
</pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
