Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- VER="v1.12"
- #======================================================================================== © 2016-2018 Martineau, v1.12
- #
- # Block unsolicited outbound traffic from the I/P cameras, except for NTP and optional WAN NVR, but still allow viewing via the VPN Servers (and/or WAN Port forwards)
- # (Default is via secure VPN servers only viewing)
- #
- # IPCamsBlock [help|-h] | [init [blockntp] [logdrop] [logntp]] | [status] | [del] | [ntplogscan | [logscan ['ip_address']] ]
- # [ wanip='ip_address[,...]' [ usewanip ] ] [mac] [ mail='mailserver[:port]]
- #
- # IPCamsBlock init
- # Create the blocking rules (usually called from /jffs/scripts/firewall-start)
- # (Assumes /jffs/configs/IPGroups exists with valid 'CAMERAS' entry - Uppercase text!)
- # e.g. CAMERAS 10.88.8.10, 10.88.8.15-10.88.8.20, 10.88.8.50:10.88.8.55 #Comment
- # IPCamsBlock init blockntp
- # Create blocking rules but NTP is also blocked (assumes cameras etc. use LAN NTP server)
- # IPCamsBlock
- # Show status of the rules in name form e.g. CAM-L-F1812 (unless 'mac' directive was used during 'init')
- # IPCamsBlock status
- # Show status of the rules in I/P form e.g. 10.88.8.10 (unless 'mac' directive was used during 'init')
- # IPCamsBlock del
- # Delete the blocking rules (NOTE: If CAMERAS list has changed since rules were created,
- # then it won't delete non-matching I/Ps!)
- # IPCamsBlock init logdrop
- # All DROPs will be logged to Syslog for analysis as to where the cameras are trying to connect to
- # IPCamsBlock init logntp
- # All NTP access requests will be logged to Syslog for analysis and displayed as part of status reuest
- # IPCamsBlock ntplogscan
- # Scan Syslog for any NTP logged entries - even if 'logntp' is not currently enabled.
- # IPCamsBlock init wan
- # Access to cameras will be via VPN and WAN Port Forwards
- # IPCamsBlock init wanaccept
- # Access to cameras will be via VPN and WAN Port Forwards and an inbound WAN 'logaccept' rule to Syslog will be created
- # IPCamsBlock init wanip=123.123.123.123
- # Access to cameras will be via VPN but LAN devices can access 123.123.123.123 via the WAN (i.e. external NVR site).
- # IPCamsBlock init wanip=1.2.3.4,9.8.7.6 usewanip
- # Access to cameras will be via VPN but the specific Cameras can access both 1.2.3.4 and 9.8.7.6 via the WAN
- # IPCamsBlock init mac
- # Use the current Camera MAC address rather than the Camera IP (Static DHCP recommended!)
- # IPCamsBlock init mail=smtp.gmail.com:587
- # Cameras can send emails to smtp.gmail.com:587
- # IPCamsBlock logscan
- # Scan Syslog for any blocking entries for ALL IP Cameras. (NOTE: 'init logdrop' must have been used.)
- # IPCamsBlock logscan 10.88.8.10
- # Scan Syslog for any blocking entries for IP Camera 10.88.8.10. (NOTE: 'init logdrop' must have been used.)
- #
- #
- # /jffs/scripts/firewall-start
- # /jffs/scripts/IPCamsBlock.sh init
- # [URL="https://www.snbforums.com/threads/help-please-need-assistance-stopping-outbound-connections.38086/page-2#post-314785"]IPCamsBlock.sh[/URL]
- # [URL="https://www.snbforums.com/threads/help-please-need-assistance-stopping-outbound-connections.38086/page-3#post-314828"]Mini WinSCP tutorial for IPCamsBlock[/URL]
- #*************************************FUNCTIONS***************************************************************
- Say(){
- echo -e $$ $@ | logger -st "($(basename $0))"
- }
- SayT(){
- echo -e $$ $@ | logger -t "($(basename $0))"
- }
- # Print between line beginning with'#==' to first blank line inclusive
- ShowHelp() {
- awk '/^#==/{f=1} f{print; if (!NF) exit}' $0
- }
- ANSIColours() {
- cRESET="\e[0m";cBLA="\e[30m";cRED="\e[31m";cGRE="\e[32m";cYEL="\e[33m";cBLU="\e[34m";cMAG="\e[35m";cCYA="\e[36m";cGRA="\e[37m"
- cBGRA="\e[90m";cBRED="\e[91m";cBGRE="\e[92m";cBYEL="\e[93m";cBBLU="\e[94m";cBMAG="\e[95m";cBCYA="\e[96m";cBWHT="\e[97m"
- aBOLD="\e[1m";aDIM="\e[2m";aUNDER="\e[4m";aBLINK="\e[5m";aREVERSE="\e[7m"
- cRED_="\e[41m";cGRE_="\e[42m"
- }
- # Function Parse(String delimiter(s) variable_names)
- Parse() {
- #
- # Parse "Word1,Word2|Word3" ",|" VAR1 VAR2 REST
- # (Effectivley executes VAR1="Word1";VAR2="Word2";REST="Word3")
- local string IFS
- TEXT="$1"
- IFS="$2"
- shift 2
- read -r -- "$@" <<EOF
- $TEXT
- EOF
- }
- Check_Router_Mode() {
- local OK=1 # Assume not Router mode
- case "$(nvram get sw_mode)" in
- 0) SW_MODE="Unconfigured";;
- 1) SW_MODE="Router";OK=0;;
- 2) SW_MODE="Repeater";;
- 3) SW_MODE="AP";;
- 4) SW_MODE="Hotspot";;
- *) SW_MODE="Unknown nvram sw_mode value="$(nvram get sw_mode);;
- esac
- echo $SW_MODE
- return $OK
- }
- Is_IPv4 () {
- grep -oE '^([0-9]{1,3}\.){3}[0-9]{1,3}$' # IPv4 format
- }
- Firewall(){
- $IPT $@ 2>/dev/null
- local RC=$?
- if [ "$RC" -gt 0 ];then # Report error for "-I" insert actions
- local FIREWALL_ERROR=$RC
- if [ "$1" == "-I" ] || [ "$1" == "-A" ];then
- echo -e "\n\a'"$IPT $@"'"
- $IPT $@
- return 1
- fi
- fi
- return 0
- }
- ExpandIPRange() {
- # '192.168.1.30 192.168.1.50-192.168.1.54' -> '192.168.1.30 192.168.1.50 192.168.1.51 192.168.1.52 192.168.1.53 192.168.1.54'
- local IP_LIST=
- local START_RANGE=
- local END_RANGE=
- local NUM=
- local MAX=
- local LANIPADDR=`nvram get lan_ipaddr`
- local LAN_PREFIX=${LANIPADDR%.*} # 1.2.3.99 -> 1.2.3
- for THIS in $@
- do
- if [ -n "$(echo "$THIS" | grep -E "^#")" ];then
- break # Ignore comment v1.07
- fi
- if [ -n "$(echo $THIS | grep -o "-")" ];then # v1.11
- Parse $THIS "-" START_RANGE END_RANGE # 1.2.3.90-1.2.3.99 -> 1.2.3.90 1.2.3.99
- local START_PREFIX=${START_RANGE%.*} # 1.2.3.90 -> 1.2.3
- local END_PREFIX=${END_RANGE%.*} # 1.2.3.99 -> 1.2.3
- if [ "$START_PREFIX" != "$END_PREFIX" ];then # Restrict range of devices to 254
- Say "***ERROR*** invalid IP range" $THIS
- echo -e"\a"
- exit 99
- fi
- NUM=${START_RANGE##*.} # Extract 4th octet 1.2.3.90 -> 90
- MAX=${END_RANGE##*.} # Extract 4th octet 1.2.3.99 -> 99
- while [ $NUM -le $MAX ]
- do
- IP_LIST=$IP_LIST" "$START_PREFIX"."$NUM
- NUM=$(($NUM+1))
- done
- else
- local THIS_PREFIX=${THIS%.*}
- if [ "$THIS_PREFIX" != "$LAN_PREFIX" ];then
- Say "***ERROR '"$THIS"' is not on this LAN '"$LAN_PREFIX".0/24'"
- echo ""
- return 1
- else
- IP_LIST=$IP_LIST" "$THIS # Add to list
- fi
- fi
- shift 1
- done
- echo $IP_LIST
- }
- Convert_TO_IP() {
- # Perform a lookup if a hostname (or I/P address) is supplied and is not known to PING
- # NOTE: etc/host.dnsmasq is in format
- #
- # I/P address hostname
- #
- local USEPATH="/jffs/configs"
- if [ -n "$1" ];then # v1.11
- if [ -z $2 ];then # Name to IP Address
- local IP_NAME=$(echo $1 | tr '[a-z]' '[A-Z]')
- local IP_RANGE=$(ping -c1 -t1 -w1 $IP_NAME 2>&1 | tr -d '():' | awk '/^PING/{print $3}')
- # 127.0.53.53 for ANDROID? https://github.com/laravel/valet/issues/115
- if [ -n "$(echo $IP_RANGE | grep -E "^127")" ];then
- local IP_RANGE=
- fi
- if [ -z "$IP_RANGE" ];then # Not PINGable so lookup static
- IP_RANGE=$(grep -i "$IP_NAME" /etc/hosts.dnsmasq | awk '{print $1}')
- #logger -s -t "($(basename $0))" $$ "Lookup '$IP_NAME' in DNSMASQ returned:>$IP_RANGE<"
- # If entry not matched in /etc /hosts.dnsmasq see if it exists in our IPGroups lookup file
- #
- # KEY I/P address[ {,|-} I/P address]
- #
- if [ -z "$IP_RANGE" ] && [ -f $USEPATH/IPGroups ];then
- #IP_RANGE=$(grep -i "^$IP_NAME" $USEPATH/IPGroups | awk '{print $2}')
- IP_RANGE=$(grep -i "^$IP_NAME" $USEPATH/IPGroups | awk '{$1=""; print $0}')
- #logger -s -t "($(basename $0))" $$ "Lookup '$IP_NAME' in '$USEPATH/IPGroups' returned:>$IP_RANGE<"
- fi
- fi
- else # IP Address to name
- IP_RANGE=$(nslookup $1 | grep "Address" | grep -v localhost | cut -d" " -f4)
- fi
- else
- local IP_RANGE= # Return a default WiFi Client????
- #IP_NAME="Nexus-7"
- #IP_RANGE=`grep -i $IP_NAME /etc/hosts.dnsmasq | awk '{print $1}'`
- #logger -s -t "($(basename $0))" $$ "DEFAULT '$IP_NAME' lookup returned:>$IP_RANGE<"
- fi
- echo $IP_RANGE
- }
- Hostname_from_IP() {
- local HOSTNAMES=
- local ITEMS=$@
- local STRIP_DOMAIN=0
- if [ -n "$(echo $@ | grep -oE "NODOMAIN")" ];then
- STRIP_DOMAIN=1
- ITEMS=$(echo "$@" | sed 's/NODOMAIN//')
- fi
- for IP in $ITEMS
- do
- local HOSTNAME=$(Convert_TO_IP "$IP" "Reverse")
- if [ -n "$HOSTNAME" ];then # v1.10
- if [ $STRIP_DOMAIN -eq 1 ];then
- local HOSTNAME=${HOSTNAME%%.*} # Strip domain e.g. 'CAM-W-JPT3815W.Martineau.lan' -> 'CAM-W-JPT3815W'
- fi
- else
- local HOSTNAME="N/A" # v1.10
- fi
- if [ -z "$HOSTNAMES" ];then
- local HOSTNAMES=$HOSTNAME # v1.10 Eliminate spurious leading space
- else
- local HOSTNAMES=$HOSTNAMES" "$HOSTNAME
- fi
- done
- echo $HOSTNAMES
- }
- Get_WAN_IF_Name() {
- local IF_NAME=$(nvram get wan0_ifname) # DHCP/Static ?
- # Usually this is probably valid for both eth0/ppp0e ?
- if [ "$(nvram get wan0_gw_ifname)" != "$IF_NAME" ];then
- local IF_NAME=$(nvram get wan0_gw_ifname)
- fi
- if [ -n "$(nvram get wan0_pppoe_ifname)" ];then
- local IF_NAME="$(nvram get wan0_pppoe_ifname)" # PPPoE
- fi
- echo $IF_NAME
- }
- Chain_exists() {
- # Args: {chain_name} [table_name]
- local CHAIN="$1"
- shift
- [ $# -eq 1 ] && local TABLE="-t $1"
- iptables $TABLE -n -L $CHAIN >/dev/null 2>&1
- local RC=$?
- if [ $RC -ne 0 ];then
- echo "N"
- return 1
- else
- echo "Y"
- return 0
- fi
- }
- Check_SkynetStatus() {
- if [ "$(nvram get wan0_proto)" = "pppoe" ] || [ "$(nvram get wan0_proto)" = "pptp" ] || [ "$(nvram get wan0_proto)" = "l2tp" ]; then
- local iface="ppp0"
- else
- local iface="$(nvram get wan0_ifname)"
- fi
- local skynetloc="$(grep -ow "skynetloc=.* # Skynet" /jffs/scripts/firewall-start 2>/dev/null | grep -vE "^#" | awk '{print $1}' | cut -c 11-)"
- local skynetipset="${skynetloc}/skynet.ipset"
- { [ -f "$skynetipset" ] && ipset -L -n Skynet-Whitelist >/dev/null 2>&1 && iptables -t raw -C PREROUTING -i "$iface" -m set ! --match-set Skynet-Whitelist src -m set --match-set Skynet-Master src -j DROP >/dev/null 2>&1; } ||
- { [ -f "$skynetipset" ] && ipset -L -n Skynet-Whitelist >/dev/null 2>&1 && iptables -t raw -C PREROUTING -i br0 -m set ! --match-set Skynet-Whitelist dst -m set --match-set Skynet-Master dst -j DROP >/dev/null 2>&1 && iptables -t raw -C OUTPUT -m set ! --match-set Skynet-Whitelist dst -m set --match-set Skynet-Master dst -j DROP >/dev/null 2>&1; }
- }
- #======================================Main==================================================================================
- Main(){}
- ANSIColours
- MYROUTER=$(nvram get computer_name)
- FIRMWARE=$(echo $(nvram get buildno) | awk 'BEGIN { FS = "." } {printf("%03d%02d",$1,$2)}')
- WAN_IF=$(Get_WAN_IF_Name)
- # Can only run in Router Mode;
- if [ "$(Check_Router_Mode)" != "Router" ];then
- echo -e $cBRED"\a\n\n\n\n\t\t\t\t** "$(Check_Router_Mode)" mode is not supported **\t\t\t\t\t\n\n\n"$cRESET
- exit 999
- fi
- # Need assistance!???
- if [ "$1" == "help" ] || [ "$1" == "-h" ]; then
- echo -e $cBWHT
- ShowHelp
- echo -e $cRESET
- exit 0
- fi
- echo -e $cBWHT
- Say $VER "I/P Cameras Firewall blocking...." $@
- VPNONLY=1 # Only allow remote viewing via a secure VPN connection
- if [ "$(echo $@ | grep -cw "wanaccept")" -eq 1 ];then
- VPNONLY=0
- fi
- IPT="/usr/sbin/iptables"
- # Check for group names, and expand as necessary
- # e.g. '192.168.1.30,192.168.1.50-192.168.1.54' -> '192.168.1.30 192.168.1.50 192.168.1.51 192.168.1.52 192.168.1.53 192.168.1.54'
- if [ -f "/jffs/configs/IPGroups" ];then # '/jffs/configs/IPGroups' two columns
- # ID xxx.xxx.xxx.xxx[[,xxx.xxx.xxx.xxx][-xxx.xxx.xxx.xxx]
- #CAMERAS=$(grep -iwE "^CAMERAS" /jffs/configs/IPGroups | awk '{print $2}') # Assume .csv format
- CAMERAS=$(grep -iwE "^CAMERAS" /jffs/configs/IPGroups | awk '{$1=""; print $0}') # All columns except 1st to allow '#comments' and
- # # spaces and ',' between IPs v1.07
- else
- #CAMERAS="10.88.8.120,10.88.8.122-10.88.8.123,10.88.8.124:10.88.8.125" # Silly example to illustrate how multiple ranges can be specified!
- CAMERAS=
- fi
- # Expand the list of camera I/Ps as necessary
- # e.g. '192.168.1.30,192.168.1.50-192.168.1.54' -> '192.168.1.30 192.168.1.50 192.168.1.51 192.168.1.52 192.168.1.53 192.168.1.54'
- CAMERAS=`echo $CAMERAS | tr ',' ' '` # CSVs ?
- CAMERAS=`echo $CAMERAS | tr ':' '-'` # Alternative range spec xxx.xxx.xxx.xxx:xxx.xxx.xxx.xxx
- # Expand any ranges
- if [ -n "$(echo $CAMERAS | grep -o "-")" ];then # xxx-yyy range ?
- CAMERAS="$(ExpandIPRange "$CAMERAS")"
- fi
- if [ -z "$CAMERAS" ];then
- echo -e $cBRED
- Say "***ERROR No Cameras defined - see /jffs/configs/IPGroups"
- echo -e "\a"$cRESET
- exit 1
- fi
- CAMERA_CNT=$(echo $CAMERAS | wc -w)
- RULECNT=$(($CAMERA_CNT+1))
- CAMERAS=$(echo $CAMERAS | tr " " "\n" | sort -r | tr "\n" " ") # Cosmetic; add rules in reverse order
- JUMP="DROP"
- if [ "$(echo "$@" | grep -cw "logdrop")" -gt 0 ];then
- # Unfortunately the creator of Skynet deems it acceptable to silently cripple intrinsic iptables diagnostic functionality - go figure!?... :-(
- # Check to see if the standard 'logdrop' chain is still functional :-(
- if [ -z "$(iptables -nL logdrop | grep -E "^LOG")" ];then
- if Check_SkynetStatus; then
- echo -en $cBRED"\a\t"
- Say "***ERROR Intrinsic 'iptables -t filter logdrop' chain functionality has been purposely CRIPPLED by ACTIVE SKynet...WTF?!!!"
- if [ "$(echo "$@" | grep -cw "fixskynet")" -gt 0 ];then
- echo -en $cBRED
- iptables -I logdrop -m state --state NEW -j LOG --log-prefix "DROP " --log-tcp-sequence --log-tcp-options --log-ip-options -m comment --comment "FUBAR'd by SKynet"
- echo -en $cBGRE"\t"
- Say ".....has now been repaired."
- iptables --line -nvL logdrop
- echo -en $cRESET
- else
- iptables --line -nvL logdrop
- echo -e $cRESET
- exit 999
- fi
- else
- echo -en $cBRED"\a\t"
- Say "***ERROR Intrinsic 'iptables -t filter logdrop' chain functionality has been purposely probably been CRIPPLED by a (temporarily) DISABLED SKynet...WTF?!!!"
- iptables --line -nvL logdrop
- echo -e $cRESET
- exit 999
- fi
- fi
- JUMP="logdrop"
- fi
- TRACK_NTP=0
- if [ "$(echo "$@" | grep -cw "logntp")" -gt 0 ];then
- TRACK_NTP=1
- fi
- NTP_SCAN=0
- if [ "$(echo "$@" | grep -cw "ntplogscan")" -gt 0 ];then
- NTP_SCAN=1
- fi
- LOG_SCAN=0 # v1.09
- if [ "$1" == "logscan" ];then
- LOG_SCAN=1
- if [ -n "$2" ];then
- CAMERAS=$2 # Scan the log for a specific IP Camera
- # Convert to IP if required
- if [ -z "$(echo "$CAMERAS" | Is_IPv4)" ];then
- CAMERAS=$(Convert_TO_IP "$2")
- fi
- fi
- fi
- WAN_IP= # Web IP address(es)
- if [ -n "$(echo "$@" | grep "wanip=")" ];then
- WAN_IP="$(echo "$@" | grep -oE "wanip=.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" | cut -d'=' -f2)"
- fi
- USEWANIP=0 # Web IP address(es) is for any device
- if [ "$(echo "$@" | grep -cw "usewanip")" -gt 0 ] && [ -n "$WAN_IP" ];then
- USEWANIP=1 # Web IP address(es) is only for CAMERA devices
- fi
- USEMAC=0 # Use MAC rather than IP address
- if [ "$(echo "$@" | grep -cw "mac")" -gt 0 ];then
- USEMAC=1
- fi
- MAIL= # Allow sending email to server e.g. mail=smtp.gmail.com:587
- if [ -n "$(echo "$@" | grep "mail=")" ];then
- MAIL="$(echo "$@" | sed -n "s/^.*mail=//p" | awk '{print $1}')"
- fi
- # When logdrop (rather than DROP target) was used:
- # Amcrest I/P camera (10.88.8.125) goes to http://54.84.228.44/ for Firmware Check/List/Update?
- # Tenvis I/P camera (10.88.8.120 goes to http://91.198.22.70/ to Identify my WAN I/P?
- echo -en $cBRED
- if [ $FIRMWARE -ge 38201 ];then # v01.04 v382.+ seems to use more chains, so to keep the FORWARD CHAIN easier to read create chain MyIPCAMs
- CHAIN="MyIPCAMs"
- else
- CHAIN="FORWARD"
- fi
- # Allow MAC comments v1.07
- IPCOMMENT=
- modprobe xt_comment 2>/dev/null
- RC=$?
- if [ $RC -eq 0 ];then
- IPCOMMENT="-m comment --comment "
- fi
- # Create or Delete rules for the specified cameras
- if [ "$1" == "init" ] || [ "$1" == "del" ];then # Called from firewall-start/nat-start ?
- # Firewall modification
- if [ "$1" == "init" ];then # Create rules (but delete them if they already exist to prevent duplicates)
- ACTIONS="-D -I"
- else
- ACTIONS="-D" # Delete rules (obviously CAMERAS variable must be the same list as when the rules were created!)
- # # but efficiently zap ALL rules if they are in a separate chain :-;
- if [ $FIRMWARE -ge 38201 ];then # v1.10
- iptables -F $CHAIN 2> /dev/null
- Firewall -D FORWARD -i br0 -j $CHAIN
- iptables -X $CHAIN 2> /dev/null
- ACTIONS=
- fi
- fi
- FWRULENO=
- for ACTION in $ACTIONS
- do
- if [ "$ACTION" == "-I" ];then
- if [ $FIRMWARE -ge 38201 ];then
- iptables -F $CHAIN 2> /dev/null
- Firewall -D FORWARD -i br0 -j $CHAIN
- iptables -X $CHAIN 2> /dev/null
- iptables -N $CHAIN
- if [ "$(Chain_exists "other2wan")" == "Y" ];then # v1.12 Allow for multiple Dual-WAN 'other2wan' references
- Firewall -I FORWARD "$(iptables -nvL FORWARD --line | grep -E -m 1 "other2wan" | awk '{print $1}')" -i br0 -j $CHAIN
- else
- Firewall -I FORWARD "$(iptables -nvL FORWARD --line | grep -E "ACCEPT all.*state RELATED,ESTABLISHED" | awk '{print $1+1}')" -i br0 -j $CHAIN
- fi
- else
- FWRULENO=$(iptables -nvL FORWARD --line | grep -E "ACCEPT all.*state RELATED,ESTABLISHED" | awk '{print $1}')
- FWRULENO=$(($FWRULENO+1))
- fi
- fi
- for CAMERA in $CAMERAS
- do
- MATCH_MAC=
- MATCH_IP="-s "$CAMERA
- if [ $USEMAC -eq 1 ];then
- MATCH_IP=
- #MACADDR=$(arp -a | grep "$CAMERA" | awk '{print $4}')
- MACADDR=$(ip neigh | grep "$CAMERA" | awk '{print $5}')
- if [ -z "$MACADDR" ];then
- # Camera not online? so see if static DHCP exists
- if [ $FIRMWARE -gt 38201 ];then
- MACADDR=$(grep $CAMERA /etc/dnsmasq.conf | grep -oE "([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}")
- else
- MACADDR=$(grep $CAMERA /etc/ethers | awk '{print $1}')
- fi
- fi
- if [ -n "$MACADDR" ];then
- MATCH_MAC="-m mac --mac-source "$MACADDR
- if [ -n "$IPCOMMENT" ];then
- COMMENT=$IPCOMMENT" "$CAMERA # v1.07
- fi
- fi
- fi
- if [ "$VPNONLY" == "1" ];then # VPN only access
- #Firewall $ACTION FORWARD -s $CAMERA -i br0 ! -o tun2+ -j DROP # v01.00
- Firewall $ACTION $CHAIN $FWRULENO $MATCH_IP $MATCH_MAC -i br0 ! -o tun2+ -j $JUMP $COMMENT # v01.01
- # Should the device have access to the WAN IP address(es)?
- if [ $USEWANIP -eq 1 ];then
- WAN_IP_LIST=$(echo $WAN_IP | tr ',' ' ') # CSVs ?
- for IP in $WAN_IP_LIST # Allow multiple addresses v1.10
- do
- Firewall $ACTION $CHAIN $FWRULENO $MATCH_IP $MATCH_MAC -d $IP -i br0 -o $WAN_IF -j ACCEPT $COMMENT
- done
- fi
- # v01.02 The following rule is belt'n' braces to explicity ensure UPnP (if still ENABLED on router) can't start a new inbound connection
- # but if using Port Forwarding it will actually Block remote viewing!
- if [ "$(nvram get wan_upnp_enable)" == "1" ];then
- Firewall $ACTION $CHAIN $FWRULENO -d $CAMERA $MATCH_MAC -i $WAN_IF -m state --state NEW -j $JUMP $COMMENT
- DUMMY=
- fi
- else # WAN Port Forward and VPN access
- # The following debug rule can be used to track successful Port Forward requests
- if [ "$1" == "del" ];then
- Firewall $ACTION $CHAIN $FWRULENO -i $WAN_IF -d $CAMERA $MATCH_MAC -j logaccept
- else
- if [ "$(echo $@ | grep -cw "wanaccept")" -eq 1 ];then
- Firewall $ACTION $CHAIN $FWRULENO -i $WAN_IF -d $CAMERA $MATCH_MAC -j logaccept
- fi
- # Should the device have access to the WAN IP address(es)?
- if [ $USEWANIP -eq 1 ];then
- WAN_IP_LIST=$(echo $WAN_IP | tr ',' ' ') # CSVs ?
- for IP in $WAN_IP_LIST # Allow multiple addresses v1.10
- do
- Firewall $ACTION $CHAIN $FWRULENO $MATCH_IP $MATCH_MAC -d $IP -i br0 -o $WAN_IF -j ACCEPT $COMMENT
- done
- fi
- fi
- # IN=eth0 OUT=br0 SRC=213.205.198.14 DST=10.88.8.120 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=31481 DF PROTO=TCP SPT=57053 DPT=81
- # Allow outbound WAN IP camera traffic that was initiated inbound via a Port Forward request, but don't allow the IP camera to initiate a new outbound WAN session
- Firewall $ACTION $CHAIN $FWRULENO $MATCH_IP $MATCH_MAC -i br0 -o $WAN_IF -m state --state NEW -j $JUMP $COMMENT
- # Allow outbound VPN camera traffic via either of the VPN servers
- Firewall $ACTION $CHAIN $FWRULENO $MATCH_IP $MATCH_MAC -i br0 -o tun2+ -j ACCEPT $COMMENT
- fi
- done
- if [ $FIRMWARE -ge 38201 ] && [ "$1" == "del" ];then
- Firewall $ACTION FORWARD -i br0 -j $CHAIN
- Firewall -F $CHAIN 2> /dev/null
- Firewall -X $CHAIN 2> /dev/null
- fi
- done
- # All cameras need to allow NTP (port 123) outbound? - Might be prudent to use router as internal NTPD?
- # NOTE: Allow NTP for ALL LAN devices (e.g. IoT devices?) rather than for the individual cameras!!! - reduces number of rules!
- for ACTION in $ACTIONS # Create rules (but delete them if they already exist to prevent duplicates) or simply Delete if requested!
- do
- if [ "$2" == "blockntp" ];then
- if [ "$ACTION" == "-I" ] && [ "$1" != "init" ];then # Don't allow NTP if 'init blockntp' requested
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -p udp -m udp --dport 123 -j ACCEPT
- fi
- else
- # Track who is referencing the external NTP server the most
- if [ "$TRACK_NTP" -eq 0 ];then
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -p udp -m udp --dport 123 -j ACCEPT
- else
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -p udp -m udp --dport 123 -j logaccept
- fi
- fi
- # Allow Global access to remote WEB IP address(es) unless 'usewanip' was specified
- if [ -n "$WAN_IP" ] && [ $USEWANIP -eq 0 ];then
- WAN_IP_LIST=$(echo $WAN_IP | tr ',' ' ') # CSVs ?
- for IP in $WAN_IP_LIST # Allow multiple addresses v1.10
- do
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -d $IP -j ACCEPT
- done
- fi
- # Allow Global access to Email server # v1.08
- if [ -n "$MAIL" ];then
- Parse $MAIL ":" SMTP SMTP_PORT
- if [ -n "$SMTP_PORT" ];then
- MATCH_SMTP_PORT="--dport "$SMTP_PORT
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -d $SMTP -p tcp $MATCH_SMTP_PORT -j ACCEPT -m comment --comment $SMTP
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -d $SMTP -p udp $MATCH_SMTP_PORT -j ACCEPT -m comment --comment $SMTP
- else
- Firewall $ACTION $CHAIN $FWRULENO -i br0 -o $WAN_IF -d $SMTP -j ACCEPT -m comment --comment $SMTP
- fi
- fi
- done
- fi
- echo -e $cBYEL
- # Display rules by I/P address or by name i.e. resolve the I/Ps
- if [ "$1" == "status" ];then
- REGEXP="|"$(echo "$CAMERAS" | sed s'/.$//' | tr " " "|" ) # v1.02 include the inbound (UPnP) rules
- if [ "$(Chain_exists "$CHAIN")" == "Y" ];then
- $IPT -nvL FORWARD --line -t filter | grep -E "$CHAIN|Chain FORWARD|^num";echo -e
- #$IPT -nvL $CHAIN --line -t filter | grep -E "$CHAIN|pkts bytes|!tun2+|udp dpt:123"$REGEXP # Display I/P Addresses
- $IPT -nvL $CHAIN --line -t filter # Display I/P Addresses
- fi
- else
- # Convert the list of I/Ps back into hostnames
- REGEXP="|"$(echo "$(Hostname_from_IP "$CAMERAS"))" | sed s'/.$//' | tr " " "|" ) # v1.02 include the inbound (UPnP) rules
- if [ "$(Chain_exists "$CHAIN")" == "Y" ];then
- $IPT -nvL FORWARD --line -t filter | grep -E "$CHAIN|Chain FORWARD|^num";echo -e
- $IPT -vL $CHAIN --line -t filter | grep -E "$CHAIN|pkts bytes|!tun2+|udp dpt:ntp"$REGEXP # Resolve I/P address in Hostnames
- fi
- fi
- echo -e $cBWHT
- if [ "$1" != "del" ];then
- if [ "$1" == "init" ];then
- Say "I/P Cameras Firewall blocking request completed."
- else
- # if the NTP rule is using 'logaccept' then report on the NTP request stats - Echo Dots and Synology NAS are frequent requesters
- iptables -C $CHAIN -i br0 -o $WAN_IF -p udp -m udp --dport 123 -j logaccept 2> /dev/null
- if [ $? -eq 0 ] || [ "$NTP_SCAN" -eq 1 ];then
- TXT=" "
- if [ "$NTP_SCAN" -eq 1 ];then
- TXT=" (Previous/Archived) "
- fi
- echo -e $cBMAG"\nNTP requestor"$TXT"statistics:\n"
- LINE=
- for ITEM in $(cat $SYSLOG | grep "DPT=123" | grep -v "BLOCKED - INBOUND" | grep -oE ' SRC=[0-9,\.]* ' | cut -c 6- | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | uniq -c)
- do
- if [ -z "$LINE" ];then
- LINE="$(printf "%-3s" "$ITEM")"
- else
- LINE="$(echo -e ${LINE}"\t"$ITEM)"
- fi
- if [ "$(echo "$LINE" | wc -w)" -eq 2 ];then
- echo -e "\t${LINE}\t("$(Hostname_from_IP "$ITEM")")"
- LINE=
- fi
- done
- echo -e $cRESET
- fi
- # Allow scanning of Syslog for the blocked packets from either a specific IP Camera or any # v1.09
- LINE=
- CNT=0
- if [ "$LOG_SCAN" -eq 1 ];then
- if [ -z "$(ps | grep -v grep | grep -m 1 syslog-ng)" ];then # v1.12
- SYSLOG="/tmp/syslog.log"
- else
- SYSLOG="/opt/var/log/messages"
- fi
- if [ $(echo "$CAMERAS" | wc -w) -eq 1 ];then # Specific IP Camera ?
- TXT="IP Camera "$CAMERAS
- CAMERAS_GREP=$CAMERAS
- # Check if the IP camera is valid
- if [ -z "$(iptables -nvL $CHAIN | grep -w "$CAMERAS")" ];then
- echo -e $cBRED"\a\t***ERROR '"$(Hostname_from_IP "$CAMERAS" "NODOMAIN")"' ("$CAMERAS") does not exist in Chain '"$CHAIN"' for 'logscan' request\n"$cRESET
- exit 999
- else
- # Check if logdrop is in effect for the target?
- if [ -z "$(iptables -nvL $CHAIN | grep -E "logdrop.*$CAMERAS")" ];then
- echo -e $cRED"\a\t**Warning IP Camera '"$(Hostname_from_IP "$CAMERAS" "NODOMAIN")"' ("$CAMERAS") does not have 'logdrop' enabled for 'logscan' request\n"$cRESET
- #exit 999
- fi
- fi
- else
- TXT="ALL IP Cameras"
- CAMERAS_GREP=$(echo $CAMERAS | sed 's/ /|/g')
- fi
- echo -en $cBCYA
- Say "BLOCKED traffic for "$TXT
- TOTAL=0
- for ITEM in $(grep -E "$CAMERAS_GREP" $SYSLOG | grep "DROP" | grep -v "$(basename $0)" | sed 's/SEQ=.*$//;s/LEN=.*DF//')
- do
- if [ -z "$LINE" ];then
- LINE="$(printf "%-3s" "$ITEM")"
- else
- case $CNT in # Cosmetic tabular column formatting
- 9) LINE=$(echo ${LINE}"\\t")$(printf "%-20s" "$ITEM");;
- 10|11|13) LINE=$(echo ${LINE}"\\t")$(printf "%-10s" "$ITEM");;
- *) LINE=$(echo ${LINE}" "$ITEM);;
- esac
- fi
- CNT=$((CNT+1))
- if [ $CNT -eq 14 ];then
- echo -e $cBBLU"\t"$LINE
- LINE=
- CNT=0
- TOTAL=$((TOTAL+1))
- fi
- done
- echo -e $cBCYA
- Say "For "$TXT" - BLOCKED traffic Syslog rule count="$TOTAL
- echo -e $cRESET
- fi
- Say "I/P Cameras Firewall blocking" $1 "request completed."
- fi
- else
- Say "I/P Cameras Firewall unblocking complete."
- fi
- echo -e $cRESET
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement