CentOS as router, transparent proxy, and much more · uwot.eu
another meaningless subtitle

CentOS as router, transparent proxy, and much more

· by fabio · Read in about 7 min · (1448 Words)
blacklist CentOS 6.4 DHCP DNS NAT router sites Squid SquidGuard transparent proxy

As usual, long story short: I’ve to setup a firewall to log traffic, block some stuff and do some other things.
– epel repo is required –
The system is made of a single CentOS machine with 2 physical network adapters:
1. eth0, connected to WAN, static IP address 192.168.0.3
2. eth1, connected to LAN, static IP address 10.0.0.124

.:. Network adapters configuration

WAN network adapter:

[root@CentOS ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="none"
HWADDR="**:**:**:**:**:**"
IPADDR=192.168.0.3
NETMASK=255.255.255.0
GATEWAY=192.168.0.1
DNS=192.168.0.1
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="***"

LAN network adapter:

[root@CentOS ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1
HWADDR=**:**:**:**:**:**
NM_CONTROLLED=no
ONBOOT="yes"
IPADDR=10.0.0.1
BOOTPROTO=none
NETMASK=255.255.255.0
USERCTL=no
TYPE=Ethernet
UUID="***"
[root@CentOS ~]# service network restart

.:. DHCP

Since we want our machine to act as a router, a pretty important part of it is a DHCP server.

[root@CentOS ~]# yum install dhcp

[root@CentOS dhcp]# vi /etc/dhcp/dhcpd.conf

The file should be similar to what follows:

option domain-name "centos";
option domain-name-servers 10.0.0.1;
default-lease-time 600;
max-lease-time 7200;
authoritative;

subnet 10.0.0.0 netmask 255.255.255.0 {
        range dynamic-bootp 10.0.0.100 10.0.0.150;
        option broadcast-address 10.0.0.255;
        option routers 10.0.0.1;
}
[root@CentOS dhcp]# service dhcpd restart
[root@CentOS dhcp]# chkconfig dhcpd on

.:. DNS

You quite likely are also interested in having a local DNS server, so here is your new friend: bind.

[root@CentOS ~]# yum install bind bind-chroot

[root@CentOS ~]# vi /etc/named.conf

The file should be similar to what follows:

options {
    listen-on port 53 { 127.0.0.1; 10.0.0.1; };
    #listen-on-v6 port 53 { ::1; };
    directory   "/var/named";
    dump-file   "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
    allow-query     { localhost; 10.0.0.0/24; };
    recursion yes;

    dnssec-enable yes;
    dnssec-validation yes;
    dnssec-lookaside auto;

    /* Path to ISC DLV key */
    bindkeys-file "/etc/named.iscdlv.key";

    managed-keys-directory "/var/named/dynamic";
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
    type hint;
    file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

Other than this, add this line to “rc.local” file, this way the setting will be persistent even after a reboot..

echo nameserver 127.0.0.1 > /etc/resolv.conf

Start bind and set it to start automatically at boot.

[root@CentOS ~]# service named restart
[root@CentOS ~]# chkconfig named on

.:. iptables rules

Save the following script, edit the server IP address, the interfaces names and add your custom rules at the end of the file.
When you are done run it, beware that it’ll override any pre-existing iptables configuration.
What the script does is basically enable NAT and redirect HTTP traffic to Squid so it can be checked and logged.

#!/bin/sh
# ------------------------------------------------------------------------------
# squid server IP
SQUID_SERVER="192.168.0.3"
# WAN interface
INTERNET="eth0"
# LAN interface
LAN_IN="eth1"
# Squid port
SQUID_PORT="3128"

# DO NOT MODIFY BELOW
# Clean old firewall
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# Load IPTABLES modules for NAT and IP conntrack support
modprobe ip_conntrack
modprobe ip_conntrack_ftp
# Setting default filter policy
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
# Unlimited access to loop back
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow UDP, DNS and Passive FTP
iptables -A INPUT -i $INTERNET -m state --state ESTABLISHED,RELATED -j ACCEPT
# set this system as a router for Rest of LAN
iptables --table nat --append POSTROUTING --out-interface $INTERNET -j MASQUERADE
iptables --append FORWARD --in-interface $LAN_IN -j ACCEPT
# unlimited access to LAN
iptables -A INPUT -i $LAN_IN -j ACCEPT
iptables -A OUTPUT -o $LAN_IN -j ACCEPT
# DNAT port 80 request comming from LAN systems to squid 3128 ($SQUID_PORT) aka transparent proxy
iptables -t nat -A PREROUTING -i $LAN_IN -p tcp --dport 80 -j DNAT --to $SQUID_SERVER:$SQUID_PORT
# if it is same system
iptables -t nat -A PREROUTING -i $INTERNET -p tcp --dport 80 -j REDIRECT --to-port $SQUID_PORT
# DROP everything and Log it
iptables -A INPUT -j LOG
iptables -A INPUT -j DROP

# custom rules
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

To make the new iptables settings permanent, issue the following two commands:

[root@CentOS ~]# service iptables save

[root@CentOS ~]# service iptables restart

.:. IPv4 forwarding

To enable IPv4 forwarding and make the setting permanent edit the following file:

[root@CentOS ~]# vi /etc/sysctl.conf

Replace the “0” with a “1” in the following line:

net.ipv4.ip_forward = 1

.:. Squid installation

Squid is our transparent proxy server.

[root@CentOS ~]# yum install squid squidGuard

[root@CentOS ~]# cd /etc/squid/

[root@CentOS squid]# vi squid.conf

“squid.conf” obviously is the main Squid configuration file, edit the file to make it looks like what follows:

cache_mem 1 GB
visible_hostname centos.centos
#
# Recommended minimum configuration:
#
acl manager proto cache_object
acl localhost src 127.0.0.1/32
#acl localhost src ::1/128
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
#acl to_localhost dst ::1/128

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 10.0.0.0/24    # RFC1918 possible internal network
#acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
#acl localnet src 192.168.0.0/16        # RFC1918 possible internal network
#acl localnet src 192.168.1.0/24 # RFC1918 possible internal network
#acl localnet src fc00::/7   # RFC 4193 local private network range
#acl localnet src fe80::/10  # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

#
# Recommended minimum Access Permission configuration:
#
# Only allow cachemgr access from localhost
http_access allow manager localhost
http_access deny manager

# Deny requests to certain unsafe ports
http_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports

# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on "localhost" is a local user
#http_access deny to_localhost

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

# Squid normally listens to port 3128
http_port 3128 transparent

# We recommend you to use at least the following line.
hierarchy_stoplist cgi-bin ?

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/spool/squid 100 16 256
cache_dir ufs /var/spool/squid 8192 16 256

# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid

# Add any of your own refresh_pattern entries above these.
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

# start squidGuard and make it point to its own configuration file
url_rewrite_program /usr/bin/squidGuard -c /etc/squid/squidGuard.conf

.:. SquidGuard

You are looking for something more advanced than plain logging? Something like for example blocking some sites? SquidGuard is the answer.
We have already installed it with squid during the precedent step, so…
First of all, download a blacklist, I use this one: shallalist.de (download on the right).
Once dowloaded, unpack it in “/var/squidGuard/” and name the blacklist folder “blacklists”.
“/etc/squid/squidGuard.conf” is the SquidGuard configuration file, the syntax is really straightforward.

[root@CentOS scripts]# vi /etc/squid/squidGuard.conf

#
# CONFIG FILE FOR SQUIDGUARD
#

# tell squidGuard where to put its log files and where the blacklists are
dbhome /var/squidGuard/blacklists
logdir /var/log/squidGuard

# specify some custom blacklists, in my case one related to porn sites and the other related to gambling sites.
dest porn {
    domainlist porn/domains
    urllist porn/urls
        log pornoaccesses
} 

dest gamble {
    domainlist gamble/domains
    urllist gamble/urls
        log gambleaccesses
}

# define the action that the system will take in case someone try to visit one of the blacklisted sites.
acl {
    default {
        pass !porn !gamble all
        redirect http://errorpage.html
    }
}

Once done with editing, build the database files used by SquidGuard, set the owner (same user as the one who run Squid, which in my case is named “squid”) and If SELinux is is enabled, reapply the default context to the blacklist files.
Make sure permissions for the log folder (“/var/log/squidGuard/” in my case) and the relative log files are set correctly, they must have the same owner of the squid process.
Enable automatic startup and reboot.

[root@CentOS ~]# squidGuard -d -C all

[root@CentOS ~]# chown -R squid:squid /var/squidGuard

[root@CentOS ~]# restorecon -Rv /var/squidGuard

chkconfig squid on

reboot

This is it.