#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use Sys::Hostname;
use List::MoreUtils qw(any);
use Data::Dumper qw(Dumper);
use Joshr::Local;
use MasterConf;
# iptables-setup: sets up /etc/sysconfig/iptables
# IF AND ONLY IF: it has a configuration for this
# exact hostname
# WE STARTED with the configs for vw7 and vw4, which are identical
my $prog=$0; $prog =~ s!.*/!!;
my $verbose;
my $dryrun;
my $force;
my $log=1; # enable logging
#my @okhosts = qw( cc.joshr.com vw5.joshr.com vw6.joshr.com p4.joshr.com xl6.joshr.com xl7.joshr.com );
my $hostname = Sys::Hostname::hostname();
############################################
# Usage() : returns usage information
sub Usage {
"$prog [--verbose] [--dryrun] [--force]: sets up /etc/sysconfig/iptables\n";
}
############################################
# call main()
main();
############################################
# main()
sub main {
GetOptions(
"verbose!" => \$verbose,
"dryrun!" => \$dryrun,
"force!" => \$force,
"log!" => \$log,
) or die Usage();
unless( -e "/etc/sysconfig/iptables") {
die "$prog: Does not exist: /etc/sysconfig/iptables\n";
}
#unless( $force || any { $hostname eq $_ } @okhosts ) {
# warn "$prog: Not setup for $hostname\n";
# die unless $force;
#}
my ($preamble, $rules, $reject, $postamble) = get_iptables_base();
my $master = new MasterConf( "/home/admin/conf/master.conf" );
# modify your rules or whathaveyou here
# xl6 and xl7 had these lines, we don't know why the 5353 one
#-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
#-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
#if ($hostname eq "xl7.joshr.com") {
if ($master->host_has_service( $hostname, 'modperl' ) ) {
my $linesref = convert_scalar_to_lines( q{
#
# (matched service 'modperl')
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
});
push(@$rules, @$linesref);
}
#if ($hostname eq "mail.joshr.com") {
if ($master->host_has_service( $hostname, 'sendmail' ) ) { # TODO: rename to 'smtp' like firehol uses
my $linesref = convert_scalar_to_lines( q{
#
# (matched service 'sendmail')
# port 143/tcp is IMAP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp -s 127.0.0.1 --dport 143 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 110 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 143 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 993 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 995 -j ACCEPT
});
push(@$rules, @$linesref);
}
#if ($hostname eq "vw3.joshr.com") {
if ($master->host_has_service( $hostname, 'cfengine' ) ) {
# for cfengine
my $linesref = convert_scalar_to_lines( q{
#
# (matched service 'cfengine')
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5308 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp --dport 5308 -j ACCEPT
});
push(@$rules, @$linesref);
}
#if ($hostname eq "cc.joshr.com") {
if ($master->host_has_service( $hostname, 'vsftpd' ) ) {
my $linesref = convert_scalar_to_lines( q{
#
# (matched service 'vsftpd')
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 20 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
});
push(@$rules, @$linesref);
}
if ($log) {
my $linesref = convert_scalar_to_lines( q{
#
# (adding logging for --log option)
-A RH-Firewall-1-INPUT -j LOG
});
unshift(@$reject, @$linesref);
}
# print the firewall rules to stdout, removing blank lines
my $content = join("\n", grep { !/^\s*$/ } @$preamble, @$rules, @$reject, @$postamble) . "\n";
print $content if $verbose;
write_etc_sysconfig_iptables( $content );
}
############################################
# this IS the configs on vw5 and vw6
#
# my ($preamble, $rules, $reject, $postamble) = get_iptables_base();
#
# *ambles, rules and reject have their leading whitespace stripped, obviously
sub get_iptables_base {
my $preamble = qq{
# created by $prog
# DO NOT EDIT THIS FILE:
# Changes will be overwitten by $prog on next run!
} .
q {
#
# "Firewall configuration (originally) written by redhat-config-securitylevel
# Manual customization of this file is not recommended."
#
# (standard preamble)
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
};
my $rules = q{
#
# (standard rules)
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m udp -p udp --dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 10000 -j ACCEPT
};
my $reject = q{
#
# (standard reject)
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
};
my $postamble = q{
#
# (standard postamble)
COMMIT
};
my $preambleref = convert_scalar_to_lines( $preamble );
my $rulesref = convert_scalar_to_lines( $rules );
my $rejectref = convert_scalar_to_lines( $reject );
my $postambleref = convert_scalar_to_lines( $postamble );
return ($preambleref, $rulesref, $rejectref, $postambleref);
}
############################################
# my $linesref = convert_scalar_to_lines( $bigblockoftextwithnewlines )
sub convert_scalar_to_lines {
my $content = shift;
my @lines = map { s/^\s*//; $_ } split(/\n/, $content); # split & remove leading whitespace
return \@lines;
}
############################################
sub write_etc_sysconfig_iptables {
my $config = shift;
unless($dryrun) {
open(FILE, "> /etc/sysconfig/iptables.tmp") || die "$prog: Couldn't write /etc/sysconfig/iptables.tmp\n";
print FILE $config;
close(FILE) || die "$prog: Couldn't close file /etc/sysconfig/iptables.tmp\n";
rename("/etc/sysconfig/iptables.tmp", "/etc/sysconfig/iptables") ||
die "$prog: Couldn't rename /etc/sysconfig/iptables.tmp to /etc/sysconfig/iptables";
}
}