0

I'm trying to find a way to block YouTube video playback on my kid's Ubuntu computer. I created a shell script to get Youtube IPs and add them to iptables for incoming packets to be dropped. To do so I grab IPs with whois -h whois.radb.net -- '-i origin AS15169'

The problem is that I not only get YouTube IPs, but all Google IPs. Thus, blocking them also blocks access to other Google services, among them Google Search, Google Drive, Google Mail, etc.

I added a few exceptions too, with a domain whitelist, but this remains not enough.

Here is the shell script:

#!/bin/bash
IPTABLES=/sbin/iptables
IP6TABLES=/sbin/ip6tables

function block_ips() {
  for THIS_IP in $1; do
    # IPv4 range
    if [[ $THIS_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+$ ]]; then
      echo "Blocking $THIS_IP"
      $IPTABLES -A funban -s $THIS_IP -j fundrop
    fi

    # IPv4
    if [[ $THIS_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      echo "Blocking $THIS_IP"
      $IPTABLES -A funban -s $THIS_IP -j fundrop
    fi

    # IPv6 range
    if [[ $THIS_IP =~ ^([0-9A-Fa-f]{0,4}:){0,7}[0-9A-Fa-f]{0,4}\/[0-9]{1,3}$ ]]; then
      echo "Blocking $THIS_IP"
      $IP6TABLES -A funban -s $THIS_IP -j fundrop
    fi

    # IPv6
    if [[ $THIS_IP =~ ^([0-9A-Fa-f]{0,4}:){0,7}[0-9A-Fa-f]{0,4}$ ]]; then
      echo "Blocking $THIS_IP"
      $IP6TABLES -A funban -s $THIS_IP -j fundrop
    fi
  done
}

function accept_ips() {
  for THIS_IP in $1; do
    # IPv4 range
    if [[ $THIS_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+$ ]]; then
      echo "Allowing $THIS_IP"
      errormessage=$(${IPTABLES} -C funban -s $THIS_IP -j ACCEPT 2>&1)
      if [[ $errormessage =~ 'Bad rule' ]]; then
        echo "  Added $THIS_IP"
        $IPTABLES -I funban -s $THIS_IP -j ACCEPT
      fi
    fi

    # IPv4
    if [[ $THIS_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      errormessage=$(${IPTABLES} -C funban -s $THIS_IP -j ACCEPT 2>&1)
      if [[ $errormessage =~ 'Bad rule' ]]; then
        echo "  Added $THIS_IP"
        $IPTABLES -I funban -s $THIS_IP -j ACCEPT
      fi
    fi

    # IPv6 range
    if [[ $THIS_IP =~ ^([0-9A-Fa-f]{0,4}:){0,7}[0-9A-Fa-f]{0,4}\/[0-9]{1,3}$ ]]; then
      errormessage=$(${IP6TABLES} -C funban -s $THIS_IP -j ACCEPT 2>&1)
      if [[ $errormessage =~ 'Bad rule' ]]; then
        echo "  Added $THIS_IP"
        $IP6TABLES -I funban -s $THIS_IP -j ACCEPT
      fi
    fi

    # IPv6
    if [[ $THIS_IP =~ ^[0-9A-Fa-f]{0,4}:([0-9A-Fa-f]{0,4}:){0,6}[0-9A-Fa-f]{0,4}$ ]]; then
      errormessage=$(${IP6TABLES} -C funban -s $THIS_IP -j ACCEPT 2>&1)
      if [[ $errormessage =~ 'Bad rule' ]]; then
        echo "  Added $THIS_IP"
        $IP6TABLES -I funban -s $THIS_IP -j ACCEPT
      fi
    fi
  done
}

function get_ip4() {
  echo "$(dig ${1} A | grep -E '^[^;]' | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')"
}

function get_ip6() {
  echo "$(dig ${1} AAAA | grep -E '^[^;]' | grep -o -E '[0-9A-Fa-f]{0,4}:([0-9A-Fa-f]{0,4}:){0,6}[0-9A-Fa-f]{0,4}')"
}

errormessage=$(${IPTABLES} -n -L funban 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Create funban (IPv4)"
  $IPTABLES -N funban
fi

errormessage=$(${IP6TABLES} -n -L funban 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Create funban (IPv6)"
  $IP6TABLES -N funban
fi

errormessage=$(${IPTABLES} -L fundrop 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Create fundrop (IPv4)"
  $IPTABLES -N fundrop
  $IPTABLES -A fundrop -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
  $IPTABLES -A fundrop -j DROP
fi

errormessage=$(${IP6TABLES} -L fundrop 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Create fundrop (IPv6)"
  $IP6TABLES -N fundrop
  $IP6TABLES -A fundrop -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
  $IP6TABLES -A fundrop -j DROP
fi

errormessage=$(${IPTABLES} -C INPUT -j funban 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Filter IPv4"
  $IPTABLES -A INPUT -j funban
fi

errormessage=$(${IP6TABLES} -C INPUT -j funban 2>&1)
if [[ $errormessage =~ 'No chain/target/match by that name' ]]; then
  echo "Filter IPv6"
  $IP6TABLES -A INPUT -j funban
fi

# Flush funban chain
$IPTABLES -F funban
$IP6TABLES -F funban

# Block all Google-related IPs. The "AS15169" is taken from
# http://networktools.nl/asinfo/google.com
# Add these IPs to make google search to work (NOTE: This is not sufficient and blocks Google searches)
block_ips "$(whois -h whois.radb.net -- '-i origin AS15169' | grep -E '^route6?\:')"

while read domain; do
  echo "Whitelisting $domain"
  accept_ips $(get_ip4 $domain)
  accept_ips $(get_ip6 $domain)
done <whitelist.txt

I am trying to find another robust solution, based on iptables (my kid is clever enough to circumvent hosts blocking, for example).

I though about mDPI netfilter but it seems it's no longer available as an iptables module in Ubuntu 20.04.

$ iptables -mndpi –help
iptables v1.8.4 (legacy): Couldn't load match `ndip':No such file or directory

Any idea?

Ross Jacobs
  • 2,962
  • 1
  • 17
  • 27
MaxAuray
  • 513
  • 1
  • 4
  • 18
  • Part of the problem is that it may not be technically possible to block YouTube without blocking google. I think all of their services hide behind one TLS certificate. – Ross Jacobs Jun 02 '20 at 06:24
  • Shfmt plus using a language in a code fence forcing syntax highlighting makes it more readable – Ross Jacobs Jun 02 '20 at 06:25
  • @RossJacobs, the code in the shell script above does indeed block all Google traffic, including YouTube, but that much more than expected. Reason why I am trying to find an alternative solution. I though about nDPI, but it seems it's no more available with latest Ubuntu release. :( – MaxAuray Jun 03 '20 at 08:03

1 Answers1

0

I recommend to deny to open any web pages by firewall rule based on <title>. Not by IP-address.

:lamp: ))) Or we can write a browser add-on to search in income file a string:

  "- YouTube</title>"

to block it.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • I assumed that you meant this as a rhetoric question which gives a solution. If you instead actually wanted to ask a question please delete this. Because for that you need to use the "Ask Question" button instead of the "Post Your Answer" button. – Yunnosch Aug 31 '23 at 05:52