Dear Board:
Below is the code for a firewall for your set-top box running CCcam. It can also be used in PC configurations, but it is designed to require as few optional commands as possible in order to be compatible with the minimalist busybox versions available in satellite receiver firmware images. It will also run just as well without CCcam, but CCcam.cfg is a convenient place to look for people who should be able to access your server.
Dynamic DNS addresses require that the firewall be updated periodically. If this is not done, clients will no longer be able to access your server when their dynamic addresses are updated. Updates may be done as often as you like, but once every 20 to 30 minutes is likely sufficient.
The firewall should
eliminate illegal users entirely and prevent anyone not authorised by you from accessing your receiver. The script below updates addresses without dropping the firewall.
Authorised users are taken from CCcam.cfg directly. Therefore, if a host or IP address is in CCcam.cfg, access will be granted from that address. If the host or IP address is not in CCcam.cfg, a user from that address will have no access.
If you wish to add an access to the firewall which is not ordinarily in CCcam.cfg, just add it to Cccam.cfg with a comment '#' symbol before it:
I have included an "allow LAN by default" safeguard so that you are not locked out of your receiver. This can be disabled if a LAN or other address you use to access your receiver is found in CCcam.cfg. There is also an "allow local host by default" rule. You should not disable this.
To use the firewall:
1.) Copy the code below to a Unix-compatible editor and save to whatever receiver directory you wish under whatever name you like. Alternatively, download the file from this link:
[Only Registered Users Can See LinksClick Here To Register] Be aware that you should not try to edit the downloaded file without a Unix editor.
2.) CHMOD the script to 755.
3.) Start the firewall in telnet using the command ./var/script/firewall.sh For convenience I have called the script firewall.sh and put it in /var/script/
4.) Once the firewall has started, check the generated HOSTS file to verify that it has been populated with valid host names, one per line.
5.) Include a crontab command for updating the firewall. Modify the root crontab below to reflect your names, passwords, and paths:
Code:
20 4 * * * wget -q "http://root:pass@127.0.0.1/cgi-bin/admin?command=reboot"
25 4 * * * ./var/script/firewall.sh start
15,45 * * * * ./var/script/firewall.sh update
The above reboots your receiver at 4:20 AM, starts the firewall 5 minutes later, then updates at 15 and 45 minutes past every hour.
Finally, I have included commented lines in the script (#### UNCOMMENT FOR USE WITHOUT CROND ####) for running without crond, but I do not recommend this. It should be done only if you have tried to find crond and are absolutely certain your firmware does not have it. Starting the firewall and then passing update timing to a sleep command will likely require a modification to a boot script to ensure the firewall starts late enough not to interfere with receiver startup.
firewall.sh
Code:
#!/bin/sh
#
#
#SLEEP=900 #### UNCOMMENT FOR USE WITHOUT CROND ####
# SET THE SLEEP VARIABLE TO THE TIME DESIRED BETWEEN DDNS REFRESHES
# UNITS ARE APPROXIMATELY EQUAL TO SECONDS. FOR REFRESH EVERY 30 MINUTES, SET SLEEP=1800
#
WDIR="/var/etc/"
# !!! CHANGE WDIR IF CCcam.cfg IS NOT LOCATED AT DEFAULT /var/etc/CCcam.cfg !!!
#
CFG=$WDIR"CCcam.cfg"
HOSTS=$WDIR"HOSTS"
IPTABLES=`which iptables`
MODULES="/lib/modules/$(uname -r)/kernel/net/ipv4/netfilter"
#
PORT=`grep "SERVER LISTEN PORT: " $CFG | cut -f5 -d" "`
# CHECK LISTEN PORT (PRESUMES DEFAULT "SERVER LISTEN PORT : <VALUE>" FORMAT IN CCCAM.CFG)
#
if [ "$PORT" = "" ]; then PORT=12000
# IF NO "SERVER LISTEN PORT : <VALUE>" IS FOUND, ASSUMES CCCAM 12000 DEFAULT
#
fi
#
awk '
#
BEGIN{
# SEARCH FOR HOST PATTERNS IN CCCAM.CFG
#
q = "[A-Z0-9a-z_~\-]*"
# THIS PATTERN MATCHES ANY ALLOWED URI CHARACTER (RFC 3986) INCLUDING "-" , "_" , AND "~"
#
h = q"\\."q"\\."q"\\."q "\|" q"\\."q"\\."q "\|" q"\\."q
# THIS PATTERN MATCHES **ANY** IPv4 (IP/32) ADDRESS AND ANY SUB-DOMAIN TO LEVEL 3
# DOMAINS SUCH AS POLICE.UK, AND POLITIE.NL WILL ALSO MATCH, BUT LET US HOPE THESE DO NOT APPEAR IN CCCAM.CFG
#
}
match ($0, h){a[substr($0, RSTART, RLENGTH)] = 1}
# PLACE MATCHES OF PATTERN "h" IN CCCAM.CFG IN ARRAY "a"
#
END{
#
for (x in a) print x
# ITERATE ARRAY "a" AND PRINT ITS INDICES
#
} ' $CFG > $HOSTS
# ALL HOSTNAMES FOUND IN CCCAM.CFG ARE LISTED ONCE IN $HOSTS (USUALLY /var/etc/HOSTS)
# CHECK FILE "$HOSTS" TO MAKE CERTAIN IT CONTAINS HOSTS AS EXPECTED
#
if [ "$CFG#" = "#" ]; then echo "CCcam.cfg not found! Check location!"; exit; fi
if [ "$IPTABLES#" = "#" ]; then echo "Iptables binary not found!"; exit; fi
if [ ! -r /var/iptables/libipt_standard.so ] ; then echo "Iptables object files not found!"; exit; fi
if [ ! -r $MODULES/ip_tables.ko ]; then echo "Kernel firewall modules not found!"; exit; fi
case "$1" in
'start')
check=`lsmod | grep -c "^ip_tables"`
if [ $check = 0 ]
then
insmod $MODULES/ip_tables.ko
fi
check=`lsmod | grep -c "^ip_conntrack"`
if [ $check = 0 ]
then
insmod $MODULES/ip_conntrack.ko
fi
check=`lsmod | grep -c "^iptable_nat"`
if [ -r $MODULES/iptable_nat.ko ] && [ $check = 0 ]
then
insmod $MODULES/iptable_nat.ko
fi
for MOD in `ls $MODULES | sed -e "s/\([^. ]*\).*/\1/"`
do
check=`lsmod | grep -c "^$MOD"`
if [ $check = 0 ] && [ $MOD != 'ip_tables' ]
then
insmod $MODULES/$MOD.ko
fi
done
LOOPBACK=`/sbin/ifconfig lo | grep 'inet addr:' | sed -e 's/.*inet addr:\([^ ]*\).*/\1/'`
INTERNAL=`/sbin/ifconfig eth0 | grep 'inet addr:' | sed -e 's/.*inet addr:\([^ ]*\).*/\1/' | cut -d"." -f1-3`.0/24
$IPTABLES -A INPUT -s $LOOPBACK -j ACCEPT
# ACCEPTS ALL INBOUND LOOPBACK TRAFFIC.
# USE CAUTION IF CHANGING THIS - DEVICE CAN BECOME INACCESSIBLE!
#
$IPTABLES -A INPUT -i eth0 -s $INTERNAL -j ACCEPT
# ACCEPTS ALL INBOUND TRAFFIC FROM LOCAL NETWORK.
# TO RESTRICT TRAFFIC BY DEVICE CHANGE $INTERNAL TO A SINGLE ADDRESS (EG. 192.168.1.1)
# OR INCLUDE A LOCAL ADDRESS IN CCCAM.CFG (EG. # 192.168.1.1, # 192.168.1.5)
#
$IPTABLES -A INPUT -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
#
if [ ! -r $HOSTS ]; then
echo "Can't read: $HOSTS."
echo "Using default rules."
fi
#
cat $HOSTS | while read HOST ; do
$IPTABLES -A INPUT -s $HOST -p tcp --dport $PORT -j ACCEPT
done
echo "Firewall is active!."
logger "Firewall is active!."
#echo "DDNS set to refresh every $SLEEP seconds." #### UNCOMMENT FOR USE WITHOUT CROND ####
#sleep $SLEEP #### UNCOMMENT FOR USE WITHOUT CROND ####
#$0 update #### UNCOMMENT FOR USE WITHOUT CROND ####
exit 1
;;
#
'stop')
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -F
$IPTABLES -X
#
echo "Firewall disabled!"
logger "Firewall disabled!"
exit 2
;;
#
'restart')
$0 stop
$0 start
#echo "DDNS set to refresh every $SLEEP seconds." #### UNCOMMENT FOR USE WITHOUT CROND ####
exit 3
;;
#
'status')
$IPTABLES -L --line-numbers
exit 4
;;
#
'update')
awk '
#
BEGIN{
q = "[A-Z0-9a-z_~\-]*"
h = q"\\."q"\\."q"\\."q "\|" q"\\."q"\\."q "\|" q"\\."q
}
match ($0, h){a[substr($0, RSTART, RLENGTH)] = 1}
END{
for (x in a) print x
} ' $CFG > $HOSTS
#while [ 1 ] ; do #### UNCOMMENT FOR USE WITHOUT CROND ####
START=`$IPTABLES -L --line-numbers | grep $PORT | head -1 | cut -f1 -d " "`
END=`$IPTABLES -L --line-numbers | grep $PORT | tail -1 | cut -f1 -d " "`
RULE=`expr $START`
cat $HOSTS | while read HOST ; do
$IPTABLES -A INPUT -s $HOST -p tcp --dport $PORT -j ACCEPT
done
while [ `expr $RULE` -le `expr $END` ] ; do
$IPTABLES -D INPUT `expr $START`
RULE=`expr $RULE + 1`
done
echo "Firewall Rules Updated!"
logger "Firewall Rules Updated!"
#sleep $SLEEP #### UNCOMMENT FOR USE WITHOUT CROND ####
#done #### UNCOMMENT FOR USE WITHOUT CROND ####
exit 5
;;
#
*)
echo "Options: $0 {start|stop|restart|status|update}"
exit 6
esac
exit 0
