Search

Monday, September 26, 2016

The Definitive How-To for BOINC with SETI@HOME on Fedora / CentOS / RedHat Linux (x64 / x86)

I rediscover these steps every time I deploy a new real or virtual machine for BOINC - need to write these down once and for all. Currently participating in SETI@HOME for over 15 years and a few Large Hedron Collider (LHC) projects from the inception of LHC@HOME; here are my BOINC Stats.

I have no headless BOINCTasks PC; all computers run their own BOINC servers and command clients all on localhost.

This post is not very original; it is basically a mashup with some tweaks of (a) http://hardforum.com/showthread.php?t=1854569 and (b) http://boinc.berkeley.edu/dev/forum_thread.php?id=7358. To install boinc attached to seti@home:

Open a terminal or over ssh
(Install BOINC Compile Essentials after becoming root (because we did basic dev most of these are already installed))
su -
yum install gcc-c++ autoconf openssl-devel automake libtool libcurl-devel

(These were some other libraries I found that the configure step requested. I don’t think all of these are absolutely necessary for a basic client-only install, but who doesn’t like a configure without warnings)
yum install libGL-devel libGLU-devel freeglut-devel libXmu-devel libXi-devel libnotify-devel xcb-util-devel libjpeg-devel git

(Create boinc user, then login as boinc user)
useradd boinc
su - boinc

(Next you’ll need to git the boinc source code; when you logged in as boinc you should have been placed in boinc’s home directory (check using pwd); then create a directory for the repository; then git it)
mkdir boinc_source
git clone https://github.com/BOINC/boinc boinc_source/


(Navigate into Repo)
cd boinc_source/

(Run _autosetup)
./_autosetup

(For the configure step there are tons of options (you can look at them by searching online or ./configure --help); for this I will just use two: no server (we are not a boinc work server) and optimize (because why not))
./configure --disable-server --enable-optimize

(Now we build the monster we just created  (note – I got a few warnings which were nothing to worry about))
make

(Now we install it – I login as root for this step (exit boinc user) so that it can install boinc with the full daemon/etc.)
exit
cd /home/boinc/boinc_source
make install

Add the boinc-client service - we check and add the service if chkconfig does not see it
chkconfig --list | grep boinc
(If the above comes up empty, add it and set correct directory ownership)
chkconfig --add boinc-client
chkconfig --list | grep boinc # should produce boinc-client   0:off 1:off 2:off 3:on   4:on   5:on   6:off

(It is okay if /var/lib/boinc does not exist in the following two commands)
chown boinc /var/lib/boinc
chgrp boinc /var/lib/boinc


(Set boinc-client to start at boot and Start the boinc daemon)
chkconfig boinc-client on
service boinc-client start
service boinc-client status

(All the boinc data files end up in the boinc user home directory. Now we log back in as boinc and go there to create/modify those files for remote access)
su - boinc

(How you setup your remote login is up to you. What I do is remove the client password and the restrict access to only my BOINCTasks computer’s static IP address. This is what I show below)
vi gui_rpc_auth.cfg
Delete the password and leave only a newline (return/enter key)
Write and save the file

(Note that this next file does not yet exist – vi will create it)
vi remote_hosts.cfg
Type in your BOINCTasks PC IP address (127.0.0.1 for localhost) and the newline
Write and save the file

(Now go back to root and restart the boinc daemon)
exit
service boinc-client restart
service boinc-client status

(Now we need to add a port to firewalld so that the BOINCTasks can communicate with the boinc client)
(This is not applicable to older distros)
If your firewall is configured to allow all traffiic on localhost 127.0.0.1 this is not required.
firewall-cmd --permanent --zone=public --add-port=31416/tcp
firewall-cmd --reload

(Now your BOINCTasks should be able to connect to the computer’s IP)

To attach to SETI@Home do:

Get your account key:
boinccmd --lookup_account http://setiathome.berkeley.edu email_address password

Then attach to seti@home using your account key:

su - boinc
boinccmd --project_attach http://setiathome.berkeley.edu account_key

boinccmd --get_state

Adjust resource limits and restart. vi the following file and adjust the numbers (example below)
vi global_prefs.xml

example of global_prefs.xml:
<global_preferences>
<source_project>http://setiathome.berkeley.edu/</source_project>
<source_scheduler>http://setiboinc.ssl.berkeley.edu/sah_cgi/cgi</source_scheduler>
<mod_time>1337766618</mod_time>
<run_on_batteries>1</run_on_batteries>
<run_if_user_active>0</run_if_user_active>
<run_gpu_if_user_active>1</run_gpu_if_user_active>
<idle_time_to_run>15</idle_time_to_run>
<suspend_if_no_recent_input>0</suspend_if_no_recent_input>
<suspend_cpu_usage>30</suspend_cpu_usage>
<leave_apps_in_memory>0</leave_apps_in_memory>
<cpu_scheduling_period_minutes>60</cpu_scheduling_period_minutes>
<max_cpus>1</max_cpus>
<max_ncpus_pct>50</max_ncpus_pct>
<cpu_usage_limit>50</cpu_usage_limit>
<disk_max_used_gb>1</disk_max_used_gb>
<disk_min_free_gb>0.1</disk_min_free_gb>
<disk_max_used_pct>5</disk_max_used_pct>
<disk_interval>300</disk_interval>
<vm_max_used_pct>20</vm_max_used_pct>
<ram_max_used_busy_pct>20</ram_max_used_busy_pct>
<ram_max_used_idle_pct>20</ram_max_used_idle_pct>
<work_buf_min_days>1</work_buf_min_days>
<work_buf_additional_days>1</work_buf_additional_days>
<confirm_before_connecting>0</confirm_before_connecting>
<hangup_if_dialed>0</hangup_if_dialed>
<max_bytes_sec_down>0</max_bytes_sec_down>
<max_bytes_sec_up>0</max_bytes_sec_up>
<daily_xfer_limit_mb>0</daily_xfer_limit_mb>
<daily_xfer_period_days>0</daily_xfer_period_days>
<dont_verify_images>0</dont_verify_images>
</global_preferences>

Restart the boinc daemon, you are done:
exit
service boinc restart

Check the status - switch to boinc account.
su - boinc
boinccmd --get_project_status

======== Projects ========
1) -----------
   name: SETI@home
   master URL: http://setiathome.berkeley.edu/
   user_name: Supratim Sanyal
   team_name: The Knights Who Say Ni!
   resource share: 100.000000
   user_total_credit: 7649132.533274
   user_expavg_credit: 4777.286713
   host_total_credit: 0.000000
   host_expavg_credit: 0.000000
   nrpc_failures: 0
   master_fetch_failures: 0
   master fetch pending: no
   scheduler RPC pending: no
   trickle upload pending: no
   attached via Account Manager: no
   ended: no
   suspended via GUI: no
   don't request more work: no
   disk usage: 0.000000
   last RPC: Mon Sep 26 17:39:52 2016

   project files downloaded: 0.000000
GUI URL:
   name: Message boards
   description: Correspond with other users on the SETI@home message boards
   URL: http://setiathome.berkeley.edu/forum_index.php
GUI URL:
   name: Help
   description: Ask questions and report problems
   URL: http://setiathome.berkeley.edu/forum_help_desk.php
GUI URL:
   name: Account
   description: View your account information
   URL: http://setiathome.berkeley.edu/home.php
GUI URL:
   name: Preferences
   description: View and modify your computing preferences
   URL: http://setiathome.berkeley.edu/prefs.php?subset=global
GUI URL:
   name: Tasks
   description: View your recent tasks
   URL: http://setiathome.berkeley.edu/results.php?userid=8104231
GUI URL:
   name: Computers
   description: View a list of the computers on which you are running SETI@Home
   URL: http://setiathome.berkeley.edu/hosts_user.php?userid=8104231
GUI URL:
   name: Team
   description: View information about your team: The Knights Who Say Ni!
   URL: http://setiathome.berkeley.edu/team_display.php?teamid=30195
GUI URL:
   name: Donate
   description: Donate to SETI@home
   URL: http://setiathome.berkeley.edu/sah_donate.php
   jobs succeeded: 0
   jobs failed: 0
   elapsed time: 0.000000
   cross-project ID: 1d3ecb3f16a31376b937493d3feb0af1

Saturday, September 24, 2016

Simple Basic Working VARNISH 4.0 Configuration: default.vcl and varnish.params for a functional HTTPD web server cache for LIGHTTPD


Ever since I started maintaining a free public IP address blocklist listing sources of brute-force attacks I am seeing and putting the list up on the lighttpd web-server for anyone to use, there has been a remarkable growth of traffic that lighttpd is being asked to service.

This blocklist is based on the jail contents of fail2ban, generated hourly from fail2ban jails using a cron job, that I describe here. My fail2ban setup including automated reporting to blocklist.de over email is documented here.

Though lighttpd is not overwhelmed yet, I decided to take some load off it and put a varnish server-side cache before it, working purely off an in-memory cache since all the web-server does is provide a static page and a hourly-updated bloc-klist.

With Varnish cache delivering web pages from memory, a load test via loader.io shows 57 milliseconds average response time with  0.0 % error rate for 100 to 250 clients over 1 minute. The varnishtop screenshot at the top was taken during this test.


It took some effort to configure varnish http cache to get it to work. Here are the configuration files for varnish reverse cache and lighttpd that I am using.

My lighttpd configuration gets lighttpd to bind to and listen on the localhost (127.0.0.1) IP address on port 65481. Varnishd uses this local lighttpd server and port as the backend and serves HTTP requests from external clients on the usual port 80 on the internet-facing interfaces.

The varnish configuration below is generic, i.e. it has no dependency on lighttpd - any httpd will work as the backend of Varnish as long as Varnish knows what IP and Port Number to use as the backend.

I am using varnish version 4.0.3 and lighttpd version 1.4.41.

# varnishd -V
varnishd (varnish-4.0.3 revision b8c4a34)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2014 Varnish Software AS
# lighttpd -V
lighttpd/1.4.41 (ssl) - a light and fast webserver
Build-Date: Aug  1 2016 14:19:06

Varnish 4.0 Configuration

/etc/varnish/default.vcl


# --
# /etc/varnish/default.vcl
# Minimal working Varnish 4.0 Configuration to serve static-only website pages from lighttpd backend
# From "Simple Basic Working VARNISH 4.0 Configuration: default.vcl and varnish.params for a functional web server cache"
# http://supratim-sanyal.blogspot.com/2016/09/simple-basic-working-varnish-40.html
# --
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "65481";
.connect_timeout = 15s;
.first_byte_timeout = 30s;
.between_bytes_timeout = 5s;
.probe = {
.request =
"HEAD / HTTP/1.1"
"Host: 127.0.0.1:65481"
"Connection: close";
.interval = 3600s; # probe backend every hour
.timeout = 15s;
.window = 40;
.threshold = 38;
.initial = 38;
}
}
sub vcl_recv {
# Uncomment if Redirecting to https.
#if (req.http.host ~ "^(?i)[wwww\.]?abadcer\.com$" && req.http.X-Forwarded-Proto != "https") {
# set req.http.x-redir = "https://" + req.http.host + req.url;
# return(synth(850, "Moved permanently"));
#}
# do not cache streams or big files for download
if (req.url ~ "^[^?]*\.(mp[34]|iso|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
return (pipe);
}
# Strip off cookies in request for my static website
if (req.url ~ "(?i)\.(?:css|gif|html|ico|jpeg|jpg|js|json|png|swf|txt|woff)(?:\?.*)?$") {
unset req.http.cookie;
}
}
sub vcl_backend_response {
# Strip off cookies in response for my static website
if (bereq.url ~ "(?i)\.(?:css|gif|html|ico|jpeg|jpg|js|json|png|swf|txt|woff)(?:\?.*)?$") {
unset beresp.http.set-cookie;
}
# Enable compression on suitable content types
if (beresp.http.content-type ~ "(text|javascript|json|plain|xml)") {
set beresp.do_gzip = true;
}
# The returned content is browser-agnostic; strip any http vary indicators in the response
if (beresp.http.Vary ~ "User-Agent") {
set beresp.http.Vary = regsuball(beresp.http.Vary, ",? *User-Agent *", "");
set beresp.http.Vary = regsub(beresp.http.Vary, "^, *", "");
if (beresp.http.Vary == "") {
unset beresp.http.Vary;
}
}
# Cache expiry after an hour (The blocklist is updated every hour), but only for normal HTTP responses
if (beresp.status < 400 ) {
set beresp.ttl = 60m;
return(deliver);
}
} #end vcl_backend_response
# Corresponding to commented out https redirection condition at top
#sub vcl_synth {
# if (resp.status == 850) {
# set resp.http.Location = req.http.x-redir;
# set resp.status = 302;
# return (deliver);
# }
#}
view raw default.vcl hosted with ❤ by GitHub

/etc/varnish/varnish.params


# --
# /etc/varnish/varnish.params
# Minimal working Varnish 4.0 Configuration to serve static-only website pages from lighttpd backend
# From "Simple Basic Working VARNISH 4.0 Configuration: default.vcl and varnish.params for a functional web server cache"
# http://supratim-sanyal.blogspot.com/2016/09/simple-basic-working-varnish-40.html
# --
# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings
# Set this to 1 to make systemd reload try to switch vcl without restart.
RELOAD_VCL=1
# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl
# Default address and port to bind to. Blank address means all IPv4
# and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted
# quad, or an IPv6 address in brackets.
#VARNISH_LISTEN_ADDRESS=192.168.1.5
#VARNISH_LISTEN_PORT=6081
VARNISH_LISTEN_ADDRESS=sanyalnet-cloud-vps.freeddns.org
VARNISH_LISTEN_PORT=80
# Admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
# Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret
# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
#VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
#VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1M"
VARNISH_STORAGE="malloc,1M"
# Default TTL used when the backend does not specify one
#VARNISH_TTL=120
VARNISH_TTL=30
# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish
# Other options, see the man page varnishd(1)
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
view raw varnish.params hosted with ❤ by GitHub

Lighttpd Configuration


#######################################################################
##
## /etc/lighttpd/lighttpd.conf
## Minimal working Varnish 4.0 Configuration to serve static-only website pages from lighttpd backend
## From "Simple Basic Working VARNISH 4.0 Configuration: default.vcl and varnish.params for a functional web server cache"
## http://supratim-sanyal.blogspot.com/2016/09/simple-basic-working-varnish-40.html
##
## check /etc/lighttpd/conf.d/*.conf for the configuration of modules.
##
#######################################################################
#######################################################################
##
## Some Variable definition which will make chrooting easier.
##
## if you add a variable here. Add the corresponding variable in the
## chroot example aswell.
##
var.log_root = "/var/log/lighttpd"
#var.server_root = "/var/www"
var.server_root = "/var/www/lighttpd"
var.state_dir = "/var/run"
var.home_dir = "/var/lib/lighttpd"
var.conf_dir = "/etc/lighttpd"
##
## run the server chrooted.
##
## This requires root permissions during startup.
##
## If you run Chrooted set the the variables to directories relative to
## the chroot dir.
##
## example chroot configuration:
##
#var.log_root = "/logs"
#var.server_root = "/"
#var.state_dir = "/run"
#var.home_dir = "/lib/lighttpd"
#var.vhosts_dir = "/vhosts"
#var.conf_dir = "/etc"
#
#server.chroot = "/srv/www"
##
## Some additional variables to make the configuration easier
##
##
## Base directory for all virtual hosts
##
## used in:
## conf.d/evhost.conf
## conf.d/simple_vhost.conf
## vhosts.d/vhosts.template
##
var.vhosts_dir = server_root + "/vhosts"
##
## Cache for mod_compress
##
## used in:
## conf.d/compress.conf
##
var.cache_dir = "/var/cache/lighttpd"
##
## Base directory for sockets.
##
## used in:
## conf.d/fastcgi.conf
## conf.d/scgi.conf
##
var.socket_dir = home_dir + "/sockets"
##
#######################################################################
#######################################################################
##
## Load the modules.
include "modules.conf"
##
#######################################################################
#######################################################################
##
## Basic Configuration
## ---------------------
##
#server.port = 80
# we are varnish backend
server.port = 65481
##
## Use IPv6?
##
#server.use-ipv6 = "enable"
server.use-ipv6 = "disable"
##
## bind to a specific IP
##
#server.bind = "sanyalnet-cloud-vps.freeddns.org"
# we are varnish backend
server.bind = "127.0.0.1"
##
## Run as a different username/groupname.
## This requires root permissions during startup.
##
server.username = "lighttpd"
server.groupname = "lighttpd"
##
## enable core files.
##
#server.core-files = "disable"
##
## Document root
##
#server.document-root = server_root + "/htdocs"
server.document-root = server_root
##
## The value for the "Server:" response field.
##
## It would be nice to keep it at "lighttpd".
##
#server.tag = "lighttpd"
server.tag = "sanyalnet-cloud-vps.freeddns.org private hobbyist http server"
##
## store a pid file
##
server.pid-file = state_dir + "/lighttpd.pid"
##
#######################################################################
#######################################################################
##
## Logging Options
## ------------------
##
## all logging options can be overwritten per vhost.
##
## Path to the error log file
##
server.errorlog = log_root + "/error.log"
##
## If you want to log to syslog you have to unset the
## server.errorlog setting and uncomment the next line.
##
#server.errorlog-use-syslog = "enable"
##
## Access log config
##
include "conf.d/access_log.conf"
##
## The debug options are moved into their own file.
## see conf.d/debug.conf for various options for request debugging.
##
include "conf.d/debug.conf"
##
#######################################################################
#######################################################################
##
## Tuning/Performance
## --------------------
##
## corresponding documentation:
## http://www.lighttpd.net/documentation/performance.html
##
## set the event-handler (read the performance section in the manual)
##
## possible options on linux are:
##
## select
## poll
## linux-sysepoll
##
## linux-sysepoll is recommended on kernel 2.6.
##
server.event-handler = "linux-sysepoll"
##
## The basic network interface for all platforms at the syscalls read()
## and write(). Every modern OS provides its own syscall to help network
## servers transfer files as fast as possible
##
## sendfile - is recommended for small files.
## writev - is recommended for sending many large files
##
server.network-backend = "sendfile"
##
## As lighttpd is a single-threaded server, its main resource limit is
## the number of file descriptors, which is set to 1024 by default (on
## most systems).
##
## If you are running a high-traffic site you might want to increase this
## limit by setting server.max-fds.
##
## Changing this setting requires root permissions on startup. see
## server.username/server.groupname.
##
## By default lighttpd would not change the operation system default.
## But setting it to 2048 is a better default for busy servers.
##
## With SELinux enabled, this is denied by default and needs to be allowed
## by running the following once : setsebool -P httpd_setrlimit on
server.max-fds = 2048
##
## Stat() call caching.
##
## lighttpd can utilize FAM/Gamin to cache stat call.
##
## possible values are:
## disable, simple or fam.
##
server.stat-cache-engine = "simple"
##
## Fine tuning for the request handling
##
## max-connections == max-fds/2 (maybe /3)
## means the other file handles are used for fastcgi/files
##
server.max-connections = 1024
##
## How many seconds to keep a keep-alive connection open,
## until we consider it idle.
##
## Default: 5
##
#server.max-keep-alive-idle = 5
##
## How many keep-alive requests until closing the connection.
##
## Default: 16
##
#server.max-keep-alive-requests = 16
##
## Maximum size of a request in kilobytes.
## By default it is unlimited (0).
##
## Uploads to your server cant be larger than this value.
##
#server.max-request-size = 0
##
## Time to read from a socket before we consider it idle.
##
## Default: 60
##
#server.max-read-idle = 60
##
## Time to write to a socket before we consider it idle.
##
## Default: 360
##
#server.max-write-idle = 360
##
## Traffic Shaping
## -----------------
##
## see /usr/share/doc/lighttpd/traffic-shaping.txt
##
## Values are in kilobyte per second.
##
## Keep in mind that a limit below 32kB/s might actually limit the
## traffic to 32kB/s. This is caused by the size of the TCP send
## buffer.
##
## per server:
##
#server.kbytes-per-second = 128
##
## per connection:
##
#connection.kbytes-per-second = 32
##
#######################################################################
#######################################################################
##
## Filename/File handling
## ------------------------
##
## files to check for if .../ is requested
## index-file.names = ( "index.php", "index.rb", "index.html",
## "index.htm", "default.htm" )
##
index-file.names = ("index.html")
##
## deny access the file-extensions
##
## ~ is for backupfiles from vi, emacs, joe, ...
## .inc is often used for code includes which should in general not be part
## of the document-root
url.access-deny = ( "~", ".inc" )
##
## disable range requests for pdf files
## workaround for a bug in the Acrobat Reader plugin.
##
$HTTP["url"] =~ "\.pdf$" {
server.range-requests = "disable"
}
##
## url handling modules (rewrite, redirect)
##
#url.rewrite = ( "^/$" => "/server-status" )
#url.redirect = ( "^/wishlist/(.+)" => "http://www.example.com/$1" )
##
## both rewrite/redirect support back reference to regex conditional using %n
##
#$HTTP["host"] =~ "^www\.(.*)" {
# url.redirect = ( "^/(.*)" => "http://%1/$1" )
#}
##
## which extensions should not be handle via static-file transfer
##
## .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
##
#static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".scgi" )
# Static Files Only for this server
static-file.exclude-extensions = ()
##
## error-handler for status 404
##
#server.error-handler-404 = "/error-handler.html"
#server.error-handler-404 = "/error-handler.php"
##
## Format: <errorfile-prefix><status-code>.html
## -> ..../status-404.html for 'File not found'
##
#server.errorfile-prefix = "/srv/www/htdocs/errors/status-"
##
## mimetype mapping
##
include "conf.d/mime.conf"
##
## directory listing configuration
##
include "conf.d/dirlisting.conf"
##
## Should lighttpd follow symlinks?
##
server.follow-symlink = "enable"
##
## force all filenames to be lowercase?
##
#server.force-lowercase-filenames = "disable"
##
## defaults to /var/tmp as we assume it is a local harddisk
##
server.upload-dirs = ( "/var/tmp" )
##
#######################################################################
#######################################################################
##
## SSL Support
## -------------
##
## To enable SSL for the whole server you have to provide a valid
## certificate and have to enable the SSL engine.::
##
## ssl.engine = "enable"
## ssl.pemfile = "/path/to/server.pem"
##
## The HTTPS protocol does not allow you to use name-based virtual
## hosting with SSL. If you want to run multiple SSL servers with
## one lighttpd instance you must use IP-based virtual hosting: ::
##
## Mitigate CVE-2009-3555 by disabling client triggered renegotation
## This is enabled by default.
##
## IMPORTANT: this setting can only be used in the global scope.
## It does *not* work inside conditionals
##
# ssl.disable-client-renegotiation = "enable"
##
## $SERVER["socket"] == "10.0.0.1:443" {
## ssl.engine = "enable"
## ssl.pemfile = "/etc/ssl/private/www.example.com.pem"
## #
## # (Following SSL/TLS Deployment Best Practices 1.3 / 17 September 2013 from:
## # https://www.ssllabs.com/projects/best-practices/index.html)
## # - BEAST is considered mitigaed on client side now, and new weaknesses have been found in RC4,
## # so it is strongly advised to disable RC4 ciphers (HIGH doesn't include RC4)
## # - It is recommended to disable 3DES too (although disabling RC4 and 3DES breaks IE6+8 on Windows XP,
## # so you might want to support 3DES for now - just remove the '!3DES' parts below).
## # - The examples below prefer ciphersuites with "Forward Secrecy" (and ECDHE over DHE (alias EDH)), remove '+kEDH +kRSA'
## # if you don't want that.
## # - SRP and PSK are not supported anyway, excluding those ('!kSRP !kPSK') just keeps the list smaller (easier to review)
## # Check your cipher list with: openssl ciphers -v '...' (use single quotes as your shell won't like ! in double quotes)
## #
## # If you know you have RSA keys (standard), you can use:
## ssl.cipher-list = "PROFILE=SYSTEM"
## # The more generic version (without the restriction to RSA keys) is
## # ssl.cipher-list = "HIGH !aNULL !3DES +kEDH +kRSA !kSRP !kPSK"
## #
## # Make the server prefer the order of the server side cipher suite instead of the client suite.
## # This option is enabled by default, but only used if ssl.cipher-list is set.
## #
## # ssl.honor-cipher-order = "enable"
## #
## server.name = "www.example.com"
##
## server.document-root = "/srv/www/vhosts/example.com/www/"
## }
##
## If you have a .crt and a .key file, cat them together into a
## single PEM file:
## $ cat /etc/ssl/private/lighttpd.key /etc/ssl/certs/lighttpd.crt \
## > /etc/ssl/private/lighttpd.pem
##
#ssl.pemfile = "/etc/ssl/private/lighttpd.pem"
##
## optionally pass the CA certificate here.
##
##
#ssl.ca-file = ""
##
#######################################################################
#######################################################################
##
## custom includes like vhosts.
##
#include "conf.d/config.conf"
#include_shell "cat /etc/lighttpd/vhosts.d/*.conf"
##
#######################################################################
view raw lighttpd.conf hosted with ❤ by GitHub

Friday, September 23, 2016

Got Fail2Ban working? Have a Web Server running? Post a public blocklist for others to use!

So I have fail2ban working, reporting happily to blocklist.de, as documented in this post.

I also happen to have lighthttpd web server running on the server. The fail2ban-client tool that is included with fail2ban can list out all the IP addresses in a jail. So I wrote a simple script to dump the banned IPs in the fail2ban jail into a file in a location under the web server's root. Then, adding it to cron, I have a free brute force attack source public IP address blocklist based on real brute-force attacks on my server. Others can use this list as one of the sources of bad IP addresses to block on their own server.

Here is the little script:


#!/bin/bash
#
# ------------
# /root/security/dump-fail2ban-blocklist.sh
# Dumps banned IPs into text file, for use by web-server for published blocklist
# Includes TOR exit nodes
# See http://supratim-sanyal.blogspot.com/2016/09/got-fail2ban-working-have-web-server.html
#
# License:
# "THE BEER-WARE LICENSE" (Revision 42):
# Supratim Sanyal <https://goo.gl/FqzyBW> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return.
# ------------
# ++
# Full path to file to create the blocklist
# --
dumpfile=/var/www/lighttpd/blocklist.txt
export TMP=/tmp
export TMPDIR=/tmp
tmpfile=/tmp/f2bd.tmp
/bin/echo "###" >$dumpfile
/bin/echo "# http://`hostname`/blocklist.txt" >>$dumpfile
/bin/echo "# `date`" >>$dumpfile
/bin/echo "# FREE IP ADDRESS BLOCKLIST WITH CIDR RANGES FOR YOUR FIREWALL" >>$dumpfile
/bin/echo "# Actual Brute force attacks to this server in last 48 hours" >>$dumpfile
/bin/echo "# And also combined IP addresses from public blocklists from" >>$dumpfile
/bin/echo "# other maintainers." >>$dumpfile
/bin/echo "# License: GNU AGPLv3 http://tuklusan.decsystem.org/agpl-3.0.txt" >>$dumpfile
/bin/echo "###" >>$dumpfile
# ++
# One line for every jail you have configured on fail2ban
# Use "fail2ban-client -q status" to see a list of configured jails
# Jail list:
# dovecot, pam-generic, postfix, postfix-rbl, postfix-sasl, sendmail-auth, sendmail-reject, sshd, sshd-ddos
# --
/bin/fail2ban-client -q status dovecot | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status pam-generic | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status postfix | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status postfix-rbl | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status postfix-sasl | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status sendmail-auth | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status sendmail-reject | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
/bin/fail2ban-client -q status sshd | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >$tmpfile
/bin/fail2ban-client -q status sshd-ddos | /bin/grep Banned | /bin/cut -c 23- | /bin/tr ' ' '\n' >>$tmpfile
# --
# ++
# Dump IP addresses blocked by pfSense at home
# --
#---- grep " filterlog: " /var/log/messages | grep "in,4" | grep "match,block" | cut -d "," -f 19 | sort | uniq | grep -v "^10.42." >>$tmpfile
# ++
# Dump whatever IPs are currently in IPSET lists
# --
ipset --list | egrep "^[0-9]" >>$tmpfile
# ++
# Dump TOR Exit Nodes
# ++
curl -o /tmp/torexit.tmp https://check.torproject.org/exit-addresses
grep ExitAddress /tmp/torexit.lis | cut -f 2 -d " " >>$tmpfile
# ++
# These tried root login
# ++
grep "Failed password for invalid user root from " /var/log/messages | cut -d " " -f 13 | egrep "^[0-9]" >>$tmpfile
/bin/sort -V $tmpfile | /bin/uniq | /bin/grep -v '^$' >>$dumpfile
numips=`/bin/grep -v '^#' $dumpfile | /bin/wc -l`
/bin/echo "###" >>$dumpfile
/bin/echo "# $numips list entries" >>$dumpfile
/bin/echo "###" >>$dumpfile
# ++
# For security, change ownership of blocklist to userid that your web servers runs under
# --
/bin/chown lighttpd:lighttpd $dumpfile
# --
/bin/chmod a+r $dumpfile
/bin/ls -l $dumpfile
/bin/cat $dumpfile
exit
And here is the cron job file saved in /etc/cron.d/dump-fail2ban-blocklist


#/etc/cron.d/dump-fail2ban-blocklist
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
MAILTO=""
HOME=/
# Every 7th minute past the hour, dump the fail2ban blocklist
7 * * * * root /root/security/dump-fail2ban-blocklist.sh >/var/log/dump-fail2ban-blocklist.log 2>&1
Remember - files in the /etc/cron.d directory should not have write permissions, i.e. the permissions on /etc/cron.d/dump-fail2ban-blocklist should be:

# ls -l /etc/cron.d/dump-fail2ban-blocklist
-r-------- 1 root root 284 Sep 23 17:22 /etc/cron.d/dump-fail2ban-blocklist



Tuesday, September 20, 2016

FAIL2BAN FOR CENTOS 7 WITH IPSET FILTERING FOR INTRUSION IP ADDRESS BLOCKING AND FEEDBACK TO BLOCKLIST.DE

This is a quick recap of how I set up fail2ban with real-time reporting to blocklist.de from my public internet-facing Virtual Private Server (sanyalnet-cloud-vps.freeddns.org) running CentOS 7.

Fail2ban continues to provide a robust first line of defense against the numerous dictionary and ddos or brute force attacks faced by any internet-facing cloud server. blocklist.de has been providing a very valuable blacklist for a long time for free, and I wanted to take this opportunity to contribute back to blocklist.de as well.

Right after installing an operating system and bringing it up, any new cloud server open to the internet should be hardened first. For my CentOS 7 installation, I found and followed a great set of basic hardening instructions at the highon.coffee blog and also made more tweaks that I documented here.

Then set up your internet email service. I installed and configured my email service to use postfix for SMTP and dovecot for POP and IMAP. I used the awesome instructions here to do so.

Fail2ban defaults to sending emails from the address of "fail2ban@<hostname>" and there is no need to change this behavior. A quick way to validate your email MTA is to install the mailx utility and confirm that outgoing emails are being sent successfully - you can send a email from the server to your gmail account, for example.

I then registered an account at blocklist.de and added my server. While adding the server, provide your current IP (dynamic IPs are okay as blocklist provides a separate email address for reporting intrusions on a server with dynamic IP). Also leave the API Key field empty - it will be filled in for you later.

blocklist.de add server form

I configured fail2ban to use ipset (instead of, and better than, iptables) to keep track of addresses to block. Check if you have ipset installed, and if not, install the ipset packages using yum install ipset. You should have the packages similar to the following installed to proceed.

# rpm -qa | grep ipset
ipset-6.19-4.el7.x86_64
ipset-libs-6.19-4.el7.x86_64

As the attackers started coming in fast and furious, fail2ban was the logical next step. Installing fail2ban is a breeze, thanks to its easy availability from the epel repository. The three steps below are all that are needed to install and bring up the initial configuration of fail2ban and get it ready for modifications needed to use ipset and send intrusion activity reports to blocklist.de.

# yum -y install epel-release
# yum -y install fail2ban
# systemctl enable fail2ban

Once the default fail2ban configuration is up and running with ipset, I created a /etc/fail2ban/jail.local file that overrides a few configuration items with what I need.
  • Default ban action is iptables-ipset-proto4
  • Since I use the free and very nice Uptime Robot service to monitor my servers, I whitelisted the Uptime Robot IPs that reach out to my server often enough to be flagged as intrusions with failed logon attempts by fail2ban. The list of IP addresses that Uptime Robot's robots use are conveniently listed on the Locations and IPs page on Uptime Robot web-site.
  • Tweaked findtime, bantime and maxretry a bit. I use a ban time of 48 hours only because blocklist.de automatically un-bans IP addresses 48 hours after adding them to their banned IP block list.
  • Adjusted destemail and sender email addresses to match with my account at blocklist.de
  • Adjusted the action to be email with log entries, i.e. %(action_mwl)s
  • Enabled the fail2ban intrusion reporting filters corresponding to the services provided by my server - ssh, postfix, sendmail and dovecot.
Here is my complete /etcfail2ban/jail.local file:

#
#/etc/fail2ban/jail.local
#
[DEFAULT]
banaction = iptables-ipset-proto4
# Whitelist private IPs, blocklist.de IPs and Uptime Robot IPs
ignoreip = 127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 89.149.254.157 89.149.237.105 89.149.242.40 80.67.29.225 80.67.16.214 78.46.95.41 89.149.201.23 85.181.13.140 178.63.159.40 78.46.91.247 78.46.91.239 69.162.124.226 69.162.124.227 69.162.124.228 69.162.124.229 69.162.124.230 69.162.124.231 69.162.124.232 69.162.124.233 69.162.124.234 69.162.124.235 69.162.124.236 69.162.124.237 69.162.124.238 46.137.190.132 122.248.234.23 188.226.183.141 178.62.52.237 54.79.28.129 54.94.142.218 104.131.107.63 54.67.10.127 54.64.67.106 159.203.30.41 46.101.250.135 108.31.82.24
# look for intrusions in last 10 minutes (in seconds)
findtime = 600
# blocklist.de unbans after 48 hours, I do the same. This is in seconds.
bantime = 172800
# number of authentication failures to get banned
maxretry = 10
destemail = fail2ban@dyn.blocklist.de
sender = fail2ban@sanyalnet-cloud-vps.freeddns.org
action = %(action_mwl)s
[sshd]
enabled = true
[sshd-ddos]
enabled = true
[postfix]
enabled = true
[postfix-rbl]
enabled = true
[sendmail-auth]
enabled = true
[sendmail-reject]
enabled = true
[dovecot]
enabled = true
maxretry = 2
view raw jail.local hosted with ❤ by GitHub

The results can be seen readily if the server name is googled. Also look at your /var/log/maillog and /var/log/fail2ban.log to verify everything is working as expected.


You can download a complete tarball of my /etc/fail2ban directory including default and custom configuration files that report intrusions to blocklist.de from my google drive.







Thursday, September 15, 2016

Free Online Public FORTUNE - COWSAY Server : Fun with TELNET and C/C++ Linux Multi-threaded Socket Server Programming (CentOS 7)

 ________________________________________
/ Necessity is the plea for every        \
| infringement of human freedom. It is   |
| the argument of tyrants; it is the     |
\ creed of slaves. -- William Pitt, 1783 /
 ----------------------------------------
    \               ,-----._
  .  \         .  ,'        `-.__,------._
 //   \      __\\'                        `-.
((    _____-'___))                           |
 `:='/     (alf_/                            |
 `.=|      |='                               |
    |)   O |                                  \
    |      |                               /\  \
    |     /                          .    /  \  \
    |    .-..__            ___   .--' \  |\   \  |
   |o o  |     ``--.___.  /   `-'      \  \\   \ |
    `--''        '  .' / /             |  | |   | \
                 |  | / /              |  | |   mmm
                 |  ||  |              | /| |
                 ( .' \ \              || | |
                 | |   \ \            // / /
                 | |    \ \          || |_|
                /  |    |_/         /_|
               /__/


Open a terminal or a command prompt, enter telnet sanyalnet-cloud-vps.freeddns.org and press Enter again quickly. A random fortune cookie message will be returned to you, formatted by cowsay.


Do it again. A different random cowsay formatted fortune cookie will be presented to you.


These are delivered by a little Linux server daemon "cowsayd" I wrote in C for really no good reason in the spirit of fortune and cowsay. Running on my CentOS 7 hobbyist VPS, the publicly accessible daemon serves cookies on the standard TELNET TCP port 23 from the Linux fortune database, which is based on Ken Arnold's BSD implementation.

After a connection is received and accepted, I require some input from the client (just pressing the Enter key suffices) before sending back a cowsay formatted fortune cookie. This is an attempt at gracefully handling the continuous connections from automated bots which are probably looking for a "username:", "login:" or some such prompt and rarely send any inputs. So I hope mostly humans will read what is shown on the screen ("Enter anything to hear the cow speak.") and react correctly to receive a fortune-cowsay message for fun.

The C / C++ program is based off my Brain-damaged http 410 server with the same features as discussed there, but with a couple of important differences:
  • This fortune/cowsay server does not need to listen to connections from more than one port, as it servers clients on just one port. Hence, the select() system call and associated family of macros are not needed by the fortune+cowsay server.
  • The server works by invoking a shell command that in turn executes fortune and cowsay and returns the output back to the server, which passes it on to the client and closes the connection. The shell command is invoked using popen() which is thread-safe in Linux, and works well for getting a message from fortune/cowsay.
  • The use of pthread_attr_setdetachstate with PTHREAD_CREATE_DETACHED is demonstrated. This server spawns a thread to service every connection and the spawned thread exits after servicing a connection. The main thread never waits to join the spawned threads. If we do not create detached threads for this scenario, memory usage will keep increasing every time a thread is spawned since the default attribute of PTHREAD_CREATE_JOINABLE will never release all service thread resources becuase it expecting the main thread to join and ask for the return value.
  • Obtaining the client IP address is demonstrated using the inet_ntop() function.
  • It logs into the same file as sshd (usually /var/log/secure) in a format designed for abusers to be picked up and banned by fail2ban if installed. fail2ban is configured on my server to also automatically email blocklist.de for more general dissemination of telnet spammers. I also maintain a blocklist file free for public use.
Both fortune and cowsay need be installed and working for this server to deliver the messages. I describe how to install them later in this article (see "How to install Fortune and Cowsay on CentOS 7" below.)

To compile the cowsayd server, we need to include the -lpthread switch on the gcc command line, since it is a multi-threaded server.

  • gcc -o cowsayd -lpthread cowsayd.c

    Once compiled, copy the binary to the directory  /usr/local/bin.

    The server is designed to run continuously. Starting it up at boot time is done by a custom init script in the /etc/init.d directory. The server logs to syslog, check /var/log/messages for log output for troubleshooting,


    Here is the complete source code of cowsayd.c.

    /* +++
    Supratim Sanyal's COWSAY server
    - If a connection is made to its network port, and if fortune and cowsay are
    - installed, this waits for some input and returns a random fortune cookie formatted by cowsay
    -
    - to build: gcc -o cowsayd -lpthread cowsayd.c
    - on Centos 7, install fortune with yum install fortune-mod
    - and install cowsay from rpm at http://www.melvilletheatre.com/articles/el7/
    -
    - derived from Brain Damaged web server (http://supratim-sanyal.blogspot.com/2016/07/httpd410server-tiny-free-web-server-to.html)
    -
    - I can be reached at http://mcaf.ee/sdlg9f
    - Posted under GPL 3.0 License - use and modify freely but retain this header
    --- */
    #include<assert.h>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<arpa/inet.h>
    #include<unistd.h>
    #include<pthread.h>
    #include<sys/time.h>
    #include<syslog.h>
    #include<errno.h>
    #include<fcntl.h>
    #include<netinet/tcp.h>
    #include<netinet/in.h>
    static const int MAXCLIENTS=10; // Should be less than /proc/sys/net/ipv4/tcp_max_syn_backlog
    static const int UID=99; // this uid is set for this program after bind() for security - 99 is nobody
    static const int GID=99; // this gid is set for this program after bind() for security - 99 is nobody
    static const int RECV_TIMEOUT=3; // seconds to wait for client to send something after connecting
    static const int MAX_RECV_RETRIES=3; // let recv timeout this many times before closing connection
    static const int TCP_PORT_NUMBER=23; // listen on telnet port
    static const int ZERO=0; // useful in setting socket options
    static const int ONE=1; // useful in setting socket options
    static const char *const banner1="COWSAY SERVER AT sanyalnet-cloud-vps.freeddns.org\n\n";
    static const char *const banner2="Enter anything to hear the cow speak.\n";
    int numclients=0;
    char cowsayresp[1024]="\0";
    const char *const shell_command="if [[ $(which cowsay > /dev/null ; echo $?) -eq 0 ]] && [[ $(which fortune > /dev/null ; echo $?) -eq 0 ]] ; then cowsay -f $(ls $(cowsay -l | awk 'NR==1 {print $4}' | sed 's/://') | shuf -n1) $(fortune); echo; fi";
    int throttle(const struct in_addr *const sin_addr, const unsigned short *const sin_port);
    //mutexes and thread functions
    pthread_mutex_t clientcount_mutex, shell_exec_mutex, param_mutex;
    pthread_attr_t thread_attr;
    pthread_t thread_id;
    void *connection_handler(void *);
    int cowsayexec()
    {
    FILE *fp;
    char c;
    int i=0,retval=0;
    fp = popen(shell_command, "r");
    if (NULL==fp)
    {
    syslog(LOG_NOTICE,"Failed to open pipe to command [%s]; error: %d/%s",shell_command, errno,strerror(errno));
    retval=-1;
    }
    else
    {
    memset(cowsayresp,0,sizeof(cowsayresp));
    for(i=0;i<(sizeof(cowsayresp)-1);i++)
    {
    if(EOF==(c=getc(fp)))
    {
    cowsayresp[i]='\0';
    break;
    }
    else
    {
    cowsayresp[i]=c;
    }
    } //for
    } //else
    pclose(fp);
    return retval;
    } //cowsayexec()
    int main(int argc , char *argv[])
    {
    int socket_desc, client_sock, c, flags;
    long long int totalserved=0; // 64 bit integer
    struct sockaddr_in server, client;
    char addrbuf[INET_ADDRSTRLEN]; /* defined in <netinet/in.h> */
    // We will enforce a timeout for clients to send something after connecting
    struct timeval recv_to_tv;
    recv_to_tv.tv_sec = RECV_TIMEOUT;
    recv_to_tv.tv_usec = 0;
    setlogmask (LOG_UPTO (LOG_INFO));
    openlog ("COWSAYD", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
    syslog(LOG_NOTICE,"%s starting up",argv[0]);
    printf("%s: see system log for messages\n",argv[0]);
    if (pthread_mutex_init(&clientcount_mutex, NULL) != 0)
    {
    syslog(LOG_NOTICE,"failed to init clientcount_mutex: %s",strerror(errno));
    closelog();
    exit(1);
    }
    if (pthread_mutex_init(&shell_exec_mutex, NULL) != 0)
    {
    syslog(LOG_NOTICE,"failed to init shell_exec_mutex: %s",strerror(errno));
    closelog();
    exit(1);
    }
    if (pthread_mutex_init(&param_mutex, NULL) != 0)
    {
    syslog(LOG_NOTICE,"failed to init param_mutex: %s",strerror(errno));
    closelog();
    exit(1);
    }
    // Our service threads will be detached threads
    // If we don't do this, threads will default to PTHREAD_CREATE_JOINABLE which
    // will keep using up memory because the thread resources are not released at
    // thread exit since they are expecting to be joined by the main thread to
    // retrieve return status etc.
    if(pthread_attr_init(&thread_attr) != 0)
    {
    syslog(LOG_NOTICE,"failed to init thread_attr: %s",strerror(errno));
    closelog();
    exit(1);
    }
    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)!= 0)
    {
    syslog(LOG_NOTICE,"failed to set detached thread attr: %s",strerror(errno));
    closelog();
    exit(1);
    }
    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
    syslog(LOG_NOTICE,"Could not create socket: %s", strerror(errno));
    closelog();
    exit(1);
    }
    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( TCP_PORT_NUMBER );
    if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &ONE, sizeof(int)) < 0)
    {
    syslog(LOG_NOTICE,"Could not set SO_REUSEADDR on socket: %s", strerror(errno));
    }
    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
    syslog(LOG_NOTICE,"Could not bind socket: %s", strerror(errno));
    closelog();
    exit(1);
    }
    if(0!=setgid(GID)) // set gid first because it cannot be done after setuid
    {
    syslog(LOG_NOTICE,"Could not setgid to [%d], proceeding regardless: %d[%s]", GID, errno, strerror(errno));
    }
    else
    {
    syslog(LOG_NOTICE,"setgid to [%d] ok", GID);
    }
    if(0!=setuid(UID))
    {
    syslog(LOG_NOTICE,"Could not setuid to [%d], proceeding regardless: %d[%s]", UID, errno, strerror(errno));
    }
    else
    {
    syslog(LOG_NOTICE,"setuid to [%d] ok", UID);
    }
    //Listen and Accept
    listen(socket_desc, 1+MAXCLIENTS); // keep queue size small to try avoid DOS flood; maximum is in proc/sys/net/ipv4/tcp_max_syn_backlog
    c = sizeof(struct sockaddr_in);
    while(client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))
    {
    if (client_sock < 0)
    {
    syslog(LOG_NOTICE,"Could not accept connection: %s", strerror(errno));
    shutdown (socket_desc, SHUT_RDWR);
    close(socket_desc);
    closelog();
    exit(1);
    }
    memset(addrbuf,0,sizeof(addrbuf));
    if (NULL==inet_ntop(AF_INET, &client.sin_addr, addrbuf, INET_ADDRSTRLEN))
    {
    syslog(LOG_NOTICE,"Could not get client address: %d[%s]", errno,strerror(errno));
    shutdown (client_sock, SHUT_RDWR);
    close(client_sock);
    }
    else
    {
    totalserved++;
    syslog(LOG_NOTICE,"ACCEPTED Connection %lld from IP %s PORT %d", totalserved, addrbuf, ntohs(client.sin_port));
    // The following lines sends an entry that looks like SSH logon failure to syslogd, to be picked up
    // by fail2ban if configured, which will ban the ip and report to blocklist.de for multiple connections quickly
    // from same IP (i.e. source is telnet DOS/spam)
    // Aug 28 21:04:36 sanyalnet-cloud-vps sshd[17400]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=static-200-105-171-226.acelerate.net
    closelog();
    openlog ("sshd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
    syslog(LOG_AUTHPRIV|LOG_WARNING,"pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=telnet ruser= rhost=%s", addrbuf);
    closelog();
    openlog ("COWSAYD", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
    pthread_mutex_lock(&param_mutex); // Lock the client_sock descriptor until connection_handler thread
    // has copied to local variable
    // set receive timeout on the accepted connection
    setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&recv_to_tv,sizeof(struct timeval));
    if(throttle(&client.sin_addr,&client.sin_port)) // TBD ... some sort of anti-DOS throttle for IP address would be nice...
    {
    syslog(LOG_NOTICE,"THROTTLED IP: %s PORT %d", addrbuf, ntohs(client.sin_port));
    shutdown (client_sock, SHUT_RDWR);
    close(client_sock);
    }
    else if( pthread_create( &thread_id , &thread_attr, connection_handler , (void*) &client_sock) < 0)
    {
    syslog(LOG_NOTICE,"Could not create service thread: %d[%s]", errno, strerror(errno));
    shutdown (client_sock, SHUT_RDWR);
    close(client_sock);
    }
    }
    } //while
    exit(0); // unreachable
    } //main()
    // Handle each connection in this created thread
    void *connection_handler(void *socket_desc)
    {
    //Get the socket descriptor
    int sock = *(int*)socket_desc;
    int i=0,read_size=0, thisclient=0, myerrno=0, recv_tries=0;
    char client_message[128]="\0";
    memset(client_message,0,sizeof(client_message));
    pthread_mutex_unlock(&param_mutex);
    pthread_mutex_lock(&clientcount_mutex);
    numclients++;
    thisclient=numclients;
    pthread_mutex_unlock(&clientcount_mutex);
    if(thisclient>MAXCLIENTS) // Client numbers start at 1 due to ++ above
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Server full, MAXCLIENTS reached",thisclient,sock);
    }
    else
    {
    // Send the banners
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &ONE, sizeof(int)); // setting TCP_NODELAY on send
    if(send(sock,banner1,strlen(banner1),0)<0)
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Could not send banner 1: %d/%s",thisclient,sock,errno,strerror(errno));
    }
    else
    {
    if(send(sock,banner2,strlen(banner2),0)<0)
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Could not send banner 2: %d/%s",thisclient,sock,errno,strerror(errno));
    }
    }
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &ZERO, sizeof(int));
    //read and log whatever the client sends
    recv_tries=0;
    do
    {
    memset(client_message,0,sizeof(client_message));
    read_size = recv(sock, client_message, sizeof(client_message)-1, 0);
    myerrno=errno;
    if(read_size < 0)
    {
    if (EAGAIN != myerrno)
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Could not read message: recv error %d",thisclient,sock,myerrno);
    read_size=0;
    break;
    }
    else
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | no data yet",thisclient,sock);
    recv_tries++;
    if(recv_tries>=MAX_RECV_RETRIES)
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | max recv retries reached, nothing received ",thisclient,sock);
    read_size=0;
    }
    }
    }
    } while(read_size<0);
    if(read_size<=0) // read_size is zero here - empty message or unexpected client disconnet - do nothing
    {
    // bots which do not send anything after connect are not served a cowsay message
    syslog(LOG_NOTICE,"Active Clients %d FD %d | recvd zero bytes", thisclient,sock);
    }
    else
    {
    if(read_size>sizeof(client_message))read_size=sizeof(client_message);
    client_message[read_size-1]='\0'; // just some unnecessary defensive coding!
    for(i=0;i<strlen(client_message);i++) if( ('\n'==client_message[i])||('\r'==client_message[i]) ) client_message[i]=' '; // Replace tabs and returns with space for logging
    syslog(LOG_NOTICE,"Active Clients %d FD %d | RECEIVED: [%s]",thisclient,sock,client_message);
    pthread_mutex_lock(&shell_exec_mutex); // One expensive shell exec at a time please
    if(0==cowsayexec()) // get the wisdom
    {
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &ONE, sizeof(int)); // setting TCP_NODELAY on send
    if(send(sock,cowsayresp,strlen(cowsayresp),0)<0)
    {
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Could not send response: %d/%s",thisclient,sock,errno,strerror(errno));
    }
    else
    {
    syslog(LOG_NOTICE,"Sent Cowsay [%s] to FD %d",cowsayresp,sock);
    }
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &ZERO, sizeof(int));
    }
    pthread_mutex_unlock(&shell_exec_mutex);
    }
    }
    syslog(LOG_NOTICE,"Active Clients %d FD %d | Goodbye", thisclient,sock);
    shutdown (sock, SHUT_RDWR);
    close(sock);
    pthread_mutex_lock(&clientcount_mutex);
    numclients--;
    pthread_mutex_unlock(&clientcount_mutex);
    return;
    } //connection_handler()
    // TBD - return 1 if IP/Port is to be throttled based on DOS attempt or abuse, 0 if not
    int throttle(const struct in_addr *const sin_addr, const unsigned short *const sin_port)
    {
    return 0;
    }
    view raw cowsayd.c hosted with ❤ by GitHub


    The init script I use to start, restart or stop the cowsayd daemon follows. Copy this to /etc/init.d/ and make it executable using chmod +x /etc/init.d/cowsayd and then chkconfig --add cowsayd to add it to the chkconfig daemon management system. If correctly done, chkconfig --list will show the cowsayd daemon and the runlevels it is enabled for. chkconfig cowsayd on will enable starting up the daemon on reboot.

    The /etc/init.d/cowsayd script is below:

    #!/bin/sh
    #
    # cowsayd Start/Stop the cowsayd daemon.
    #
    # chkconfig: 2345 90 60
    # description: cowsayd is a minimal telnet server to return a fortune+cowsay cookie and exit
    # Supratim Sanyal - supratim at riseup dot net
    # Copy this to /etc/init.d, chmod +x and chkconfig --add.
    #
    # Source function library.
    . /etc/init.d/functions
    PIDFILE=/var/run/cowsayd.pid
    start() {
    echo -n "Starting cowsayd"
    if [ -f $PIDFILE ]; then
    PID=`cat $PIDFILE`
    echo already running: $PID
    exit 2;
    else
    #daemon --user=root --pidfile=$PIDFILE exec /usr/local/bin/cowsayd>/dev/null 2>&1 &
    daemon --check cowsayd --user=root --pidfile=$PIDFILE /usr/local/bin/cowsayd>/dev/null 2>&1 &
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/cowsayd
    return $RETVAL
    fi
    }
    stop() {
    echo -n "Shutting down cowsayd"
    echo
    killproc cowsayd
    echo
    rm -f /var/lock/subsys/cowsayd
    return 0
    }
    case "$1" in
    start)
    start
    ;;
    stop)
    stop
    ;;
    status)
    status cowsayd
    ;;
    restart)
    stop
    start
    ;;
    *)
    echo "Usage: {start|stop|status|restart}"
    exit 1
    ;;
    esac
    exit $?
    view raw cowsayd hosted with ❤ by GitHub


    HOW TO INSTALL FORTUNE and COWSAY on CentOS 7

     _________________________________________
    / Did you hear that Captain Crunch, Sugar \
    | Bear, Tony the Tiger, and Snap, Crackle |
    | and Pop were all murdered recently...   |
    | Police suspect the work of a cereal     |
    \ killer!                                 /
     -----------------------------------------
        \               ,-----._
      .  \         .  ,'        `-.__,------._
     //   \      __\\'                        `-.
    ((    _____-'___))                           |
     `:='/     (alf_/                            |
     `.=|      |='                               |
        |)   O |                                  \
        |      |                               /\  \
        |     /                          .    /  \  \
        |    .-..__            ___   .--' \  |\   \  |
       |o o  |     ``--.___.  /   `-'      \  \\   \ |
        `--''        '  .' / /             |  | |   | \
                     |  | / /              |  | |   mmm
                     |  ||  |              | /| |
                     ( .' \ \              || | |
                     | |   \ \            // / /
                     | |    \ \          || |_|
                    /  |    |_/         /_|
                   /__/


    All CentOS package installations are usually via the yum tool. Use yum install <rpm-filename> to install RPM packages.

    The Fortune RPM fortune-mod-1.99.1-17.el7.x86_64.rpm is easily available from the EPEL repository. If you have not added the EPEL repository already follow these steps:

    • head over to http://dl.fedoraproject.org/pub/epel/7/x86_64/e and download the latest epel-release*.rpm  (epel-release-7-8.noarch.rpm at the time of writing).
    • Install and enable the EPEL release repository: 
      • rpm -Uvh epel-release*rpm
    With EPEL repository enabled, fortune can be simply installed using:
    • yum install fortune-mod
    Cowsay is implemented in perl, and is therefore a set of perl scripts with no dependency on architecture as long as there is a usable perl interpreter installed, which should be the case with most installations of CentOS. If perl is not available, install perl first using yum install perl.

    To install cowsay, you need cowsay-3.03-20.el7.noarch.rpm, and optionally cowsay-beefymiracle-1.0-6.fc24.noarch.rpm and cowsay-morecows-1.0-11.4.casjay.el7.x86_64.rpm. The latter two provide various additional cows and other assorted animal art.

    With the EPEL repository enabled, cowsay can be easily installed using:

    • yum install cowsay

    Then yum install the beefymiracle and morecows RPMs - if the links above do not work, use the download link to my google drive at the bottom of this post.

    HOW TO ENABLE FORTUNE - COWSAY MESSAGE ON LOGIN

     _________________________________________
    / We are preparing to think about         \
    | contemplating preliminary work on plans |
    | to develop a schedule for producing the |
    | 10th Edition of the Unix Programmers    |
    \ Manual. -- Andrew Hume                  /
     -----------------------------------------
     \                   .,
       \         .      .TR   d'
         \      k,l    .R.b  .t .Je
           \   .P q.   a|.b .f .Z%
               .b .h  .E` # J: 2`     .
          .,.a .E  ,L.M'  ?:b `| ..J9!`.,
           q,.h.M`   `..,   ..,""` ..2"`
           .M, J8`   `:       `   3;
       .    Jk              ...,   `^7"90c.
        j,  ,!     .7"'`j,.|   .n.   ...
       j, 7'     .r`     4:      L   `...
      ..,m.      J`    ..,|..    J`  7TWi
      ..JJ,.:    %    oo      ,. ....,
        .,E      3     7`g.M:    P  41
       JT7"'      O.   .J,;     ``  V"7N.
       G.           ""Q+  .Zu.,!`      Z`
       .9.. .         J&..J!       .  ,:
          7"9a                    JM"!
             .5J.     ..        ..F`
                78a..   `    ..2'
                    J9Ksaw0"'
                   .EJ?A...a.
                   q...g...gi
                  .m...qa..,y:
                  .HQFNB&...mm
                   ,Z|,m.a.,dp
                .,?f` ,E?:"^7b
                `A| . .F^^7'^4,
                 .MMMMMMMMMMMQzna,
             ...f"A.JdT     J:    Jp,
              `JNa..........A....af`
                   `^^^^^'`


    To get a mood-lifting fortune-cowsay message every time you log in, create a file /etc/profile.d/custom.sh with the following contents.

    # /etc/profile.d/custom.sh - get a fortune-cowsay message on logging in
    if [[ $(which cowsay > /dev/null ; echo $?) -eq 0 ]] && [[ $(which fortune > /dev/null ; echo $?) -eq 0 ]] ; then
    cowsay -f $(ls $(cowsay -l | awk 'NR==1 {print $4}' | sed 's/://') | shuf -n1) $(fortune)
    echo
    fi
    view raw custom.sh hosted with ❤ by GitHub


    DOWNLOAD

    You can download everything you need for free, including the cowsayd source, binary, init script, login script and Fortune and Cowsay RPMs for CentOS 7 from my google drive.



    Thursday, September 1, 2016

    Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall

    Linux iptables, included in Centos 7 distribution, provides a mechanism to block basic network attacks. This is a guide to set up basic iptables firewall rules to protect your server from some of the most common and simplest network attacks.



    Since you are here reading this, I assume you already have iptables installed and running, i.e. the command systemctl status iptables produces an output similar to this:

    iptables.service - IPv4 firewall with iptables
       Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: disabled)
       Active: active (exited) since Mon 2016-08-22 23:37:19 UTC; 1 weeks 2 days ago
     Main PID: 598 (code=exited, status=0/SUCCESS)
       CGroup: /system.slice/iptables.service

    Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

    Also disable the Centos 7 firewalld daemon. It attempts to provide an interface to manipulating iptables which I do not want and do not use at all.

    # systemctl stop firewalld
    # systemctl disable firewalld

    The first step now is to examine your existing rules with line numbers.

    # iptables -nL --line-numbers

    If you have no rules defined, you will see empty lists:

    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination

    Chain FORWARD (policy ACCEPT)
    num  target     prot opt source               destination

    Chain OUTPUT (policy ACCEPT)
    num  target     prot opt source               destination

    Otherwise, if some rules are defined, you will see them with line numbers, as in the following example of what I see. Note: I use fail2ban and custom blocklist scripts; the following example includes the resulting rules.

    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination
    1    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 110,995,143,993,587,465,4190 match-set f2b-dovecot src reject-with icmp-port-unreachable
    2    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587,220,993,110,995 match-set f2b-postfix-sasl src reject-with icmp-port-unreachable
    3    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix src reject-with icmp-port-unreachable
    4    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-sendmail-reject src reject-with icmp-port-unreachable
    5    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix-rbl src reject-with icmp-port-unreachable
    6    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 587,465,25 match-set f2b-sendmail-auth src reject-with icmp-port-unreachable
    7    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 8080 match-set f2b-squid src reject-with icmp-port-unreachable
    8    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd-ddos src reject-with icmp-port-unreachable
    9    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd src reject-with icmp-port-unreachable
    10   ACCEPT     all  --  64.137.248.161       0.0.0.0/0
    11   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set blacklist src
    12   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set blacklistnet src
    13   IP4BOGONS  all  --  0.0.0.0/0            0.0.0.0/0
    14   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 110,995,143,993,587,465,4190 match-set f2b-dovecot src reject-with icmp-port-unreachable
    15   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-sendmail-reject src reject-with icmp-port-unreachable
    16   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587,220,993,110,995 match-set f2b-postfix-sasl src reject-with icmp-port-unreachable
    17   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 587,465,25 match-set f2b-sendmail-auth src reject-with icmp-port-unreachable
    18   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix-rbl src reject-with icmp-port-unreachable
    19   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 8080 match-set f2b-squid src reject-with icmp-port-unreachable
    20   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 25,465,587 match-set f2b-postfix src reject-with icmp-port-unreachable
    21   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd-ddos src reject-with icmp-port-unreachable
    22   REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 22 match-set f2b-sshd src reject-with icmp-port-unreachable
    23   ACCEPT     all  --  64.137.248.161       0.0.0.0/0
    24   DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set block src
    25   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:!0x17/0x02 state NEW
    26   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:0x3F/0x3F
    27   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp flags:0x3F/0x00
    28   DROP       all  -f  0.0.0.0/0            0.0.0.0/0
    29   ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    30   ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
    31   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
    32   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:23
    33   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:25
    34   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:53
    35   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:53
    36   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:80
    37   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:110
    38   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:123
    39   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:143
    40   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:443
    41   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:465
    42   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:587
    43   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:993
    44   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:995
    45   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:4190
    46   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:8080
    47   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0            udp dpt:65514
    48   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:65515
    49   REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

    Chain FORWARD (policy ACCEPT)
    num  target     prot opt source               destination
    1    REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

    Chain OUTPUT (policy ACCEPT)
    num  target     prot opt source               destination
    1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0

    Chain IP4BOGONS (1 references)
    num  target     prot opt source               destination
    1    RETURN     all  --  10.0.0.0/8           0.0.0.0/0
    2    RETURN     all  --  172.16.0.0/12        0.0.0.0/0
    3    RETURN     all  --  192.168.0.0/16       0.0.0.0/0
    4    DROP       all  --  0.0.0.0/0            0.0.0.0/0            match-set fullbogons-ipv4 src

    In any case, we start by inserting a rule at the top of, i.e. line number 1, the ACCEPT list to drop fragmented packets. This blocks IP fragmentation exploits like IP fragment overlapped (teardrop), IP fragmentation buffer full, IP fragment overrun, IP fragment too many data-grams, IP fragment incomplete, IP Fragment Too Small and similar attacks. We use the -I switch with iptables to insert a rule at a position 1.

    # iptables -I INPUT 1 -f -j DROP

    Next, we stop Null Scans, which are basically a bunch of TCP packets with sequence number 0 and no flags set. Such packets are not used in proper network communications, and are used to find open ports or holes by hackers. The following command will insert the rule at the top of the ACCEPT table, pushing the existing rules down by one line.

    # iptables -I INPUT 1 -p tcp --tcp-flags ALL NONE -j DROP

    We next stop TCP "Christmas Tree" packets - unusual packets that have all flags set. These packets are used by hackers to explore the security and features of servers, and often provide clues to the underlying operating system because operating systems react differently to such packets. Again we insert this rule at the top (line number 1), pushing existing rules down.

    # iptables -I INPUT 1 -p tcp --tcp-flags ALL ALL -j DROP

    Finally we attempt to check TCP SYN Flood attacks by inserting a rule at the top.

    # iptables -I INPUT 1 -p tcp ! --syn -m state --state NEW -j DROP

    After executing these four commands, the first four rules in the ACCEPT change should show the resulting iptables firewall rules, followed by whatever other rules existed before.

    # iptables -nL --line-numbers
    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination
    1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:!0x16/0x02 state NEW
    2    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:0x3F/0x3F
    3    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:0x3F/0x00
    4    DROP       all  -f  0.0.0.0/0            0.0.0.0/0
    ...
    ...
    ...

    Making it permanent

    We need to make the changes permanent, i.e. persistent across system restarts and reboots. On my server, iptables starts up on reboot using the default rules file /etc/sysconfig/iptables and then eventually other applications add what they need later on (e.g. a script I run to block of malware / attack sources based on publicly available blocklists, fail2ban jails created by fail2ban, etc.).

    Therefore, I just saved the four rules in the default iptables system configuration file /etc/sysconfig/iptables


    # ----------
    # /etc/sysconfig/iptables
    # Supratim Sanyal's Hobbyist Cloud VPS Server
    #
    # fail2ban and ip blocklist scripts add entries after boot, extending
    # these initial startup filter rules
    #
    # See "Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall"
    # at http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
    # ----------
    #
    #
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    #
    # --
    # Basic Network Exploit Protection from syn flood, nul, christmas and fragmented packets
    # --
    -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
    -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
    -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
    -A INPUT -f -j DROP
    #
    # --
    # Allow related connections to come in for processes initiating outgoing connections
    # --
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    #
    # --
    # Allow everything on localhost lo (127.0.0.1) interface
    # --
    -A INPUT -i lo -j ACCEPT
    -A OUTPUT -o lo -j ACCEPT
    #
    # --
    # Accept incoming connections on the following ports
    # --
    #
    # --- SSH ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
    #
    # --- TELNET ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 23 -j ACCEPT
    #
    # --- SMTP ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT
    #
    # --- DNS: TCP and UDP ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
    -A INPUT -p udp -m udp --dport 53 -j ACCEPT
    #
    # --- HTTP ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
    #
    # --- POP ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT
    #
    # --- NTP ---
    -A INPUT -p udp -m udp --dport 123 -j ACCEPT
    #
    # --- IMAP ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT
    #
    # --- HTTPS ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
    #
    # --- SMTPS ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT
    #
    # --- IMAP over SSL/TLS ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT
    #
    # --- POP3 over SSL/TLS ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 995 -j ACCEPT
    #
    # --- WEB PROXY (SQUID -> PRIVOXY -> TOR Proxy Chain) ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT
    #
    # --- RSYSLOG ---
    -A INPUT -p udp -m udp --dport 65514 -j ACCEPT
    #
    # --- STUNNEL (to RSYSLOG) ---
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 65515 -j ACCEPT
    #
    # --
    # Reject everything else, including forwarding requests
    # --
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    #
    # --
    # That's all, folks
    # --
    COMMIT
    view raw iptables hosted with ❤ by GitHub
    Finally, please make sure your /etc/sysctl.conf file has some server hardening parameters, including for securing your network. Here is mine.


    # --
    # /etc/sysctl.conf
    # From "Centos 7 Network Hardening: How to Protect Your Server from Basic Network Attacks using IPTABLES Firewall"
    # http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
    # --
    # System default settings live in /usr/lib/sysctl.d/00-system.conf.
    # To override those settings, enter new settings here, or in an /etc/sysctl.d/<name>.conf file
    #
    # For more information, see sysctl.conf(5) and sysctl.d(5).
    net.ipv6.conf.all.disable_ipv6 = 1
    # From https://highon.coffee/blog/security-harden-centos-7/
    net.ipv4.ip_forward = 0
    net.ipv4.conf.all.send_redirects = 0
    net.ipv4.conf.default.send_redirects = 0
    net.ipv4.tcp_max_syn_backlog = 1280
    net.ipv4.icmp_echo_ignore_broadcasts = 1
    net.ipv4.conf.all.accept_source_route = 0
    net.ipv4.conf.all.accept_redirects = 0
    net.ipv4.conf.all.secure_redirects = 0
    net.ipv4.conf.all.log_martians = 1
    net.ipv4.conf.default.log_martians = 1
    net.ipv4.conf.default.accept_source_route = 0
    net.ipv4.conf.default.accept_redirects = 0
    net.ipv4.conf.default.secure_redirects = 0
    net.ipv4.icmp_echo_ignore_broadcasts = 1
    net.ipv4.icmp_ignore_bogus_error_responses = 1
    net.ipv4.tcp_syncookies = 1
    net.ipv4.conf.all.rp_filter = 1
    net.ipv4.conf.default.rp_filter = 1
    net.ipv4.tcp_timestamps = 0
    # bump up size of tracked connections table
    # helps in avoiding "nf_conntrack: table full, dropping packet" errors
    net.netfilter.nf_conntrack_generic_timeout=120
    net.netfilter.nf_conntrack_max = 524288
    # misc
    fs.suid_dumpable = 0
    kernel.randomize_va_space = 2
    kernel.exec-shield = 1
    vm.overcommit_memory = 2
    view raw sysctl.conf hosted with ❤ by GitHub



    Starter /etc/sysconfig/iptables

    You can use the following iptables as the starting point. Simply copy and put it into /etc/sysconfig/iptables and then adjust the ports that it opens up for the services your server provides.

    # ----------------------------
    # /etc/sysconfig/iptables
    # Basic iptables initial rules for servers
    # Protects from common attacks and opens up service ports to incoming connections
    #
    # See http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
    #
    # Supratim Sanyal <supratim at riseup dot net>
    # ----------------------------
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    #
    # ---
    # Basic network security - resist IP fragmentation, NULL scan, Christmas Tree and TCP SYN flood attacks - Supratim Sanyal
    # See http://supratim-sanyal.blogspot.com/2016/09/centos-7-network-hardening-how-to_19.html
    # ---
    -I INPUT 1 -f -j DROP
    -I INPUT 1 -p tcp --tcp-flags ALL NONE -j DROP
    -I INPUT 1 -p tcp --tcp-flags ALL ALL -j DROP
    -I INPUT 1 -p tcp ! --syn -m state --state NEW -j DROP
    #
    # ---
    # Accept packets related to established connections (i.e. allow incoming connections to processes that initiated outgoing connections)
    # ---
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    #
    # ---
    # Allow ping response
    # ---
    -A INPUT -p icmp -j ACCEPT
    #
    # ---
    # Allow all traffic on localhost
    # ---
    -A INPUT -i lo -j ACCEPT
    -A OUTPUT -o lo -j ACCEPT
    #
    # ---
    # Open up incoming connections to servers on this box
    # ---
    #
    # HECNET
    -A INPUT -p udp -m udp --dport 4711 -j ACCEPT
    #
    # SSH
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
    #
    # Proxy Server
    -A INPUT -p tcp -m tcp --dport 12345 -j ACCEPT
    #
    # SMTP
    -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
    #
    # ---
    # Reject all other incoming and forwarding requests
    # ---
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    #
    # ---
    # The End
    # ---
    #
    COMMIT

    Recommended Products from Amazon