├── LICENSE ├── getdomainnames.sh ├── IPSET_Netflix_Domains.sh ├── IPSET_Netflix.sh └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Xentrk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /getdomainnames.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #_______________________________________________________________________________________________________________ 3 | # 4 | # This script will format the output stored in 'myfile' created using the command: tail -f dnsmasq.log > myfile 5 | # and save the output to myfile_domains. The file name 'myfile' is an example. You can enter any name. 6 | # 7 | # Usage Instructions: 8 | # 1. Navigate to the log file directory /opt/var/log 9 | # 2. Enter the command: tail -f dnsmasq.log > myfile 10 | # 3. Access the streaming service and watch some videos for a few seconds and select each option to generate 11 | # domain names. 12 | # 4. Type 'Ctrl-C' to exit 13 | # 5. Navigate to /jffs/scripts 14 | # 6. Run getdomainnames.sh 15 | # 7. The domains collected will be stored in /opt/var/log/ directory using the same name as the output file 16 | # with '_domains' concatenated at the end of the file name (e.g myfile_domains) 17 | # 18 | # Parameters Passed 19 | # $1 = provide the name of the source file when running the script 20 | # $2 = IPv4 address of client device that was used to query domains 21 | # Usage Example: 22 | # sh getdomainnames.sh myfile 192.168.1.50 23 | #_______________________________________________________________________________________________________________ 24 | 25 | # Print between line beginning with '#_' to first blank line inclusive 26 | ShowHelp() { 27 | awk '/^#__/{f=1} f{print; if (!NF) exit}' "$0" | more 28 | } 29 | 30 | # Need assistance!??? 31 | if [ "$1" = "help" ] || [ "$1" = "-h" ]; then 32 | ShowHelp 33 | exit 0 34 | fi 35 | 36 | [ -z "$1" ] && echo "Error! Missing parameter 1" && exit 1 37 | [ -z "$2" ] && echo "Error! Missing parameter 2" && exit 1 38 | 39 | SOURCE_FILE="/opt/var/log/$1" 40 | IPv4="$2" 41 | 42 | A=$(echo "$IPv4" | grep -oE "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$") 43 | 44 | if [ -z "$A" ]; then 45 | printf 'Error! "%s" is not a valid IPv4 address\n' "$IPv4" 46 | exit 1 47 | fi 48 | 49 | if [ -s "$SOURCE_FILE" ]; then 50 | OUTPUT_FILE="${SOURCE_FILE}_domains" 51 | true >"$OUTPUT_FILE" 52 | grep "$IPv4" "$SOURCE_FILE" | grep "query" | awk '{ print $6 }' | sort -u >>"$OUTPUT_FILE" 53 | else 54 | echo "Error! $SOURCE_FILE does not exist" 55 | fi 56 | -------------------------------------------------------------------------------- /IPSET_Netflix_Domains.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #################################################################################################### 3 | # Script: IPSET_Netflix_Domains.sh 4 | # Version 1.0.1 5 | # Author: Xentrk 6 | # Date: 7-September-2018 7 | # 8 | # Description: 9 | # Selective Routing Script for Netflix using Asuswrt-Merlin firmware. This version uses the ipset method 10 | # built into dnsmasq. 11 | # 12 | # Grateful: 13 | # Thank you to @Martineau on snbforums.com for sharing his Selective Routing expertise 14 | # and on-going support! 15 | # 16 | #################################################################################################### 17 | logger -t "($(basename "$0"))" $$ Starting Script Execution 18 | 19 | # Uncomment the line below for debugging 20 | #set -x 21 | 22 | PROGNAME=$(basename "$0") 23 | LOCKFILE_DIR=/tmp 24 | LOCK_FD=200 25 | 26 | lock() { 27 | local prefix=$1 28 | local fd=${2:-$LOCK_FD} 29 | local lock_file=$LOCKFILE_DIR/$prefix.lock 30 | 31 | # create lock file 32 | eval "exec $fd>$lock_file" 33 | 34 | # acquier the lock 35 | flock -n "$fd" \ 36 | && return 0 \ 37 | || return 1 38 | } 39 | 40 | error_exit() { 41 | error_str="$@" 42 | logger -t "($(basename "$0"))" $$ "$error_str" 43 | exit 1 44 | } 45 | 46 | main() { 47 | lock "$PROGNAME" || error_exit "Exiting $PROGNAME. Only one instance of $PROGNAME can run at one time." 48 | 49 | ### Define interface/bitmask to route traffic to below 50 | set_fwmark_parms () { 51 | FWMARK_WAN="0x8000/0x8000" 52 | FWMARK_OVPNC1="0x1000/0x1000" 53 | FWMARK_OVPNC2="0x2000/0x2000" 54 | FWMARK_OVPNC3="0x4000/0x4000" 55 | FWMARK_OVPNC4="0x7000/0x7000" 56 | FWMARK_OVPNC5="0x3000/0x3000" 57 | } 58 | 59 | create_fwmarks () { 60 | # WAN 61 | ip rule del fwmark "$FWMARK_WAN" 2>/dev/null 62 | ip rule add from 0/0 fwmark "$FWMARK_WAN" table 254 prio 9990 63 | 64 | #VPN Client 1 65 | ip rule del fwmark "$FWMARK_OVPNC1" 2>/dev/null 66 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC1" table 111 prio 9995 67 | 68 | #VPN Client 2 69 | ip rule del fwmark "$FWMARK_OVPNC2" 2>/dev/null 70 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC2" table 112 prio 9994 71 | 72 | #VPN Client 3 73 | ip rule del fwmark "$FWMARK_OVPNC3" 2>/dev/null 74 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC3" table 113 prio 9993 75 | 76 | #VPN Client 4 77 | ip rule del fwmark "$FWMARK_OVPNC4" 2>/dev/null 78 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC4" table 114 prio 9992 79 | 80 | #VPN Client 5 81 | ip rule del fwmark "$FWMARK_OVPNC5" 2>/dev/null 82 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC5" table 115 prio 9991 83 | 84 | ip route flush cache 85 | } 86 | 87 | 88 | # Chk_Entware function provided by @Martineau at snbforums.com 89 | 90 | Chk_Entware () { 91 | 92 | # ARGS [wait attempts] [specific_entware_utility] 93 | 94 | local READY=1 # Assume Entware Utilities are NOT available 95 | local ENTWARE="opkg" 96 | ENTWARE_UTILITY= # Specific Entware utility to search for 97 | local MAX_TRIES=30 98 | 99 | if [ -n "$2" ] && [ -n "$(echo "$2" | grep -E '^[0-9]+$')" ];then 100 | local MAX_TRIES=$2 101 | fi 102 | 103 | if [ -n "$1" ] && [ -z "$(echo "$1" | grep -E '^[0-9]+$')" ];then 104 | ENTWARE_UTILITY=$1 105 | else 106 | if [ -z "$2" ] && [ -n "$(echo "$1" | grep -E '^[0-9]+$')" ];then 107 | MAX_TRIES=$1 108 | fi 109 | fi 110 | 111 | # Wait up to (default) 30 seconds to see if Entware utilities available..... 112 | local TRIES=0 113 | 114 | while [ "$TRIES" -lt "$MAX_TRIES" ];do 115 | if [ -n "$(which "$ENTWARE")" ] && [ "$("$ENTWARE" -v | grep -o "version")" == "version" ];then 116 | if [ -n "$ENTWARE_UTILITY" ];then # Specific Entware utility installed? 117 | if [ -n "$("$ENTWARE" list-installed "$ENTWARE_UTILITY")" ];then 118 | READY=0 # Specific Entware utility found 119 | else 120 | # Not all Entware utilities exists as a stand-alone package e.g. 'find' is in package 'findutils' 121 | if [ -d /opt ] && [ -n "$(find /opt/ -name "$ENTWARE_UTILITY")" ];then 122 | READY=0 # Specific Entware utility found 123 | fi 124 | fi 125 | else 126 | READY=0 # Entware utilities ready 127 | fi 128 | break 129 | fi 130 | sleep 1 131 | logger -st "($(basename "$0"))" $$ "Entware" $ENTWARE_UTILITY "not available - wait time" $((MAX_TRIES - TRIES-1))" secs left" 132 | local TRIES=$((TRIES + 1)) 133 | done 134 | 135 | return $READY 136 | } 137 | 138 | # check if /jffs/configs/dnsmasq.conf.add contains entry for Netflix domains 139 | check_dnsmasq () { 140 | 141 | DNSMASQ_PARM_OLD="ipset=/amazonaws.com/netflix.com/nflxext.com/nflximg.net/nflxso.net/nflxvideo.net/x3mRouting_NETFLIX_DNSMASQ" 142 | DNSMASQ_PARM_NEW="ipset=/amazonaws.com/netflix.com/nflxext.com/nflximg.net/nflxso.net/nflxvideo.net/dvd.netflix.com/x3mRouting_NETFLIX_DNSMASQ" 143 | 144 | if [ -s /jffs/configs/dnsmasq.conf.add ]; then # dnsmasq.conf.add file exists 145 | if [ "$(grep -c "$DNSMASQ_PARM_OLD" "/jffs/configs/dnsmasq.conf.add")" -eq "1" ]; then # see if line exists for x3mRouting_NETFLIX_DNSMASQ 146 | sed -i "\\~$DNSMASQ_PARM_OLD~d" "/jffs/configs/dnsmasq.conf.add" 147 | fi 148 | if [ "$(grep -c "$DNSMASQ_PARM_NEW" "/jffs/configs/dnsmasq.conf.add")" -eq "0" ]; then # see if line exists for x3mRouting_NETFLIX_DNSMASQ 149 | echo "$DNSMASQ_PARM_NEW" >> /jffs/configs/dnsmasq.conf.add # add NETFLIX entry to dnsmasq.conf.add 150 | service restart_dnsmasq > /dev/null 2>&1 151 | fi 152 | else 153 | echo "$DNSMASQ_PARM_NEW\n" > /jffs/configs/dnsmasq.conf.add # dnsmasq.conf.add does not exist, create dnsmasq.conf.add 154 | service restart_dnsmasq > /dev/null 2>&1 155 | fi 156 | } 157 | 158 | check_ipset_list () { 159 | if [ "$(ipset list -n x3mRouting_NETFLIX_DNSMASQ 2>/dev/null)" != "x3mRouting_NETFLIX_DNSMASQ" ]; then #does NETFLIX ipset list exist? 160 | if [ -s /opt/tmp/x3mRouting_NETFLIX_DNSMASQ ]; then # does x3mRouting_NETFLIX_DNSMASQ ipset restore file exist? 161 | ipset restore -! < /opt/tmp/x3mRouting_NETFLIX_DNSMASQ # Restore ipset list if restore file exists at /opt/tmp/x3mRouting_NETFLIX_DNSMASQ 162 | else 163 | ipset create x3mRouting_NETFLIX_DNSMASQ hash:net family inet hashsize 1024 maxelem 65536 # No restore file, so create x3mRouting_NETFLIX_DNSMASQ ipset list from scratch 164 | fi 165 | fi 166 | } 167 | 168 | # if ipset list NETFLIX is older than 24 hours, save the current ipset list to disk 169 | check_NETFLIX_restore_file_age () { 170 | if [ -s /opt/tmp/x3mRouting_NETFLIX_DNSMASQ ]; then 171 | if [ "$(find /opt/tmp/x3mRouting_NETFLIX_DNSMASQ -name x3mRouting_NETFLIX_DNSMASQ -mtime +1 -print 2>/dev/null)" = "/opt/tmp/x3mRouting_NETFLIX_DNSMASQ" ] ; then 172 | ipset save x3mRouting_NETFLIX_DNSMASQ > /opt/tmp/x3mRouting_NETFLIX_DNSMASQ 173 | fi 174 | fi 175 | } 176 | 177 | # If cronjob to back up the NETFLIX ipset list every 24 hours @ 2:00 AM does not exist, then create it 178 | check_cron_job () { 179 | cru l | grep x3mRouting_NETFLIX_DNSMASQ_ipset_list 180 | if [ "$?" = "1" ]; then # no cronjob entry found, create it 181 | cru a x3mRouting_NETFLIX_DNSMASQ "0 2 * * * ipset save x3mRouting_NETFLIX_DNSMASQ > /opt/tmp/x3mRouting_NETFLIX_DNSMASQ" 182 | fi 183 | } 184 | 185 | # Route Netflix to WAN 186 | create_routing_rules () { 187 | iptables -t mangle -D PREROUTING -i br0 -m set --match-set x3mRouting_NETFLIX_DNSMASQ dst -j MARK --set-mark "$FWMARK_WAN" 2>/dev/null 188 | iptables -t mangle -A PREROUTING -i br0 -m set --match-set x3mRouting_NETFLIX_DNSMASQ dst -j MARK --set-mark "$FWMARK_WAN" 2>/dev/null 189 | } 190 | 191 | set_fwmark_parms 192 | create_fwmarks 193 | Chk_Entware 194 | check_dnsmasq 195 | check_ipset_list 196 | check_NETFLIX_restore_file_age 197 | check_cron_job 198 | create_routing_rules 199 | 200 | logger -t "($(basename "$0"))" $$ Completed Script Execution 201 | } 202 | main 203 | -------------------------------------------------------------------------------- /IPSET_Netflix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #################################################################################################### 3 | # Script: IPSET_Netflix.sh 4 | # Author: Xentrk 5 | # 7-September-018 Version 4.0 6 | # 7 | # Thank you to @Martineau on snbforums.com for educating myself and others on Selective 8 | # Routing techniques using Asuswrt-Merlin firmware. 9 | # 10 | # Support Thread: https://www.snbforums.com/threads/selective-routing-for-netflix.42661/ 11 | # 12 | ##################################################################################################### 13 | # Script Description: 14 | # 15 | # Selectively route Netflix traffic to the WAN interface or OpenVPN interface on 16 | # Asuswrt-Merlin firmware. 17 | # 18 | # Since January 2016, Netflix blocks known VPN servers. The purpose of the IPSET_Netflix.sh 19 | # script is to bypass the OpenVPN Client for Netflix traffic and route it to the WAN interface. 20 | # Netflix also hosts on Amazon AWS servers. Because of this, the script will also route Amazon AWS 21 | # traffic, including Amazon and Amazon Prime traffic, to the WAN interface. 22 | # 23 | ####################################################################### 24 | logger -t "($(basename "$0"))" $$ Starting Script Execution 25 | 26 | # Uncomment the line below for debugging 27 | #set -x 28 | 29 | FILE_DIR="/opt/tmp" 30 | 31 | 32 | # Prevent script from running concurrently when called from nat-start 33 | 34 | PROGNAME=$(basename "$0") 35 | LOCKFILE_DIR=/tmp 36 | LOCK_FD=200 37 | 38 | lock() { 39 | local prefix=$1 40 | local fd=${2:-$LOCK_FD} 41 | local lock_file=$LOCKFILE_DIR/$prefix.lock 42 | 43 | # create lock file 44 | eval "exec $fd>$lock_file" 45 | 46 | # acquier the lock 47 | flock -n $fd \ 48 | && return 0 \ 49 | || return 1 50 | } 51 | 52 | error_exit() { 53 | error_str="$@" 54 | logger -t "($(basename "$0"))" $$ "$error_str" 55 | exit 1 56 | } 57 | 58 | main() { 59 | lock "$PROGNAME" || error_exit "Exiting $PROGNAME. Only one instance of $PROGNAME can run at one time." 60 | 61 | # Create shared-SelectiveRouting-whitelist file if one does not exist 62 | # to prevent ipinfo.io from being blocked by AB-Solution and Skynet 63 | 64 | whitelist_ipinfo () { 65 | if [ ! -s "/jffs/shared-SelectiveRouting-whitelist" ];then 66 | printf "ipinfo.io\n" > /jffs/shared-SelectiveRouting-whitelist 67 | fi 68 | } 69 | 70 | #Download Netflix AS2906 IPv4 addresses 71 | 72 | download_AS2906 () { 73 | curl https://ipinfo.io/AS2906 2>/dev/null | grep -E "a href.*2906\/" | grep -v ":" | sed 's/^.*//' > /opt/tmp/x3mRouting_NETFLIX 74 | } 75 | 76 | # if ipset list NETFLIX does not exist, create it 77 | 78 | check_netflix_ipset_list_exist () { 79 | if [ "$(ipset list -n x3mRouting_NETFLIX 2>/dev/null)" != "x3mRouting_NETFLIX" ]; then 80 | ipset create x3mRouting_NETFLIX hash:net family inet hashsize 1024 maxelem 65536 81 | fi 82 | } 83 | 84 | # if ipset list NETFLIX is empty or source file is older than 24 hours, download source file; load ipset list 85 | check_netflix_ipset_list_values () { 86 | if [ "$(ipset -L x3mRouting_NETFLIX 2>/dev/null | awk '{ if (FNR == 7) print $0 }' | awk '{print $4 }')" -eq "0" ]; then 87 | if [ ! -s "$FILE_DIR/x3mRouting_NETFLIX" ] || [ "$(find "$FILE_DIR" -name x3mRouting_NETFLIX -mtime +7 -print)" = "$FILE_DIR/x3mRouting_NETFLIX" ]; then 88 | download_AS2906 89 | fi 90 | awk '{print "add x3mRouting_NETFLIX " $1}' "$FILE_DIR/x3mRouting_NETFLIX" | ipset restore -! 91 | else 92 | if [ ! -s "$FILE_DIR/x3mRouting_NETFLIX" ]; then 93 | download_AS2906 94 | fi 95 | fi 96 | } 97 | 98 | # Prevent entware funcion jq from executing until entware has mounted 99 | # Chk_Entware function provided by @Martineau 100 | 101 | Chk_Entware () { 102 | 103 | # ARGS [wait attempts] [specific_entware_utility] 104 | 105 | local READY=1 # Assume Entware Utilities are NOT available 106 | local ENTWARE="opkg" 107 | ENTWARE_UTILITY= # Specific Entware utility to search for 108 | local MAX_TRIES=30 109 | 110 | if [ ! -z "$2" ] && [ ! -z "$(echo $2 | grep -E '^[0-9]+$')" ];then 111 | local MAX_TRIES=$2 112 | fi 113 | 114 | if [ ! -z "$1" ] && [ -z "$(echo $1 | grep -E '^[0-9]+$')" ];then 115 | ENTWARE_UTILITY=$1 116 | else 117 | if [ -z "$2" ] && [ ! -z "$(echo $1 | grep -E '^[0-9]+$')" ];then 118 | MAX_TRIES=$1 119 | fi 120 | fi 121 | 122 | # Wait up to (default) 30 seconds to see if Entware utilities available..... 123 | local TRIES=0 124 | 125 | while [ $TRIES -lt $MAX_TRIES ];do 126 | if [ ! -z "$(which $ENTWARE)" ] && [ "$($ENTWARE -v | grep -o "version")" == "version" ];then 127 | if [ ! -z "$ENTWARE_UTILITY" ];then # Specific Entware utility installed? 128 | if [ ! -z "$($ENTWARE list-installed $ENTWARE_UTILITY)" ];then 129 | READY=0 # Specific Entware utility found 130 | else 131 | # Not all Entware utilities exists as a stand-alone package e.g. 'find' is in package 'findutils' 132 | if [ -d /opt ] && [ ! -z "$(find /opt/ -name $ENTWARE_UTILITY)" ];then 133 | READY=0 # Specific Entware utility found 134 | fi 135 | fi 136 | else 137 | READY=0 # Entware utilities ready 138 | fi 139 | break 140 | fi 141 | sleep 1 142 | logger -st "($(basename $0))" $$ "Entware" $ENTWARE_UTILITY "not available - wait time" $((MAX_TRIES - TRIES-1))" secs left" 143 | local TRIES=$((TRIES + 1)) 144 | done 145 | 146 | return $READY 147 | } 148 | 149 | # Download Amazon AWS json file 150 | 151 | download_AMAZONAWS () { 152 | wget https://ip-ranges.amazonaws.com/ip-ranges.json -O /opt/tmp/ip-ranges.json 153 | 154 | for REGION in us-east-1 us-east-2 us-west-1 us-west-2 155 | do 156 | jq '.prefixes[] | select(.region=='\"$REGION\"') | .ip_prefix' < "$FILE_DIR/ip-ranges.json" | sed 's/"//g' | sort -u >> "$FILE_DIR/x3mRouting_AMAZONAWS" 157 | done 158 | rm -rf /opt/tmp/ip-ranges.json 159 | } 160 | 161 | # if ipset AMAZONAWS does not exist, create it 162 | 163 | check_amazonaws_ipset_list_exist () { 164 | if [ "$(ipset list -n x3mRouting_AMAZONAWS 2>/dev/null)" != "x3mRouting_AMAZONAWS" ]; then 165 | ipset create x3mRouting_AMAZONAWS hash:net family inet hashsize 1024 maxelem 65536 166 | fi 167 | } 168 | 169 | # if ipset list AMAZONAWS is empty or source file is older than 24 hours, download source file; load ipset list 170 | 171 | check_amazonaws_ipset_list_values () { 172 | if [ "$(ipset -L x3mRouting_AMAZONAWS 2>/dev/null | awk '{ if (FNR == 7) print $0 }' | awk '{print $4 }')" -eq "0" ]; then 173 | if [ ! -s "$FILE_DIR/x3mRouting_AMAZONAWS" ] || [ "$(find "$FILE_DIR" -name x3mRouting_AMAZONAWS -mtime +7 -print)" = "$FILE_DIR/x3mRouting_AMAZONAWS" ]; then 174 | download_AMAZONAWS 175 | fi 176 | awk '{print "add x3mRouting_AMAZONAWS " $1}' "$FILE_DIR/x3mRouting_AMAZONAWS" | ipset restore -! 177 | else 178 | if [ ! -s "$FILE_DIR/x3mRouting_AMAZONAWS" ]; then 179 | download_AMAZONAWS 180 | fi 181 | fi 182 | } 183 | 184 | # Create fwmark for WAN and OpenVPN Interfaces 185 | 186 | create_fwmarks () { 187 | # WAN 188 | ip rule del fwmark "$FWMARK_WAN" > /dev/null 2>&1 189 | ip rule add from 0/0 fwmark "$FWMARK_WAN" table 254 prio 9990 190 | 191 | #VPN Client 1 192 | ip rule del fwmark "$FWMARK_OVPNC1" > /dev/null 2>&1 193 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC1" table 111 prio 9995 194 | 195 | #VPN Client 2 196 | ip rule del fwmark "$FWMARK_OVPNC2" > /dev/null 2>&1 197 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC2" table 112 prio 9994 198 | 199 | #VPN Client 3 200 | ip rule del fwmark "$FWMARK_OVPNC3" > /dev/null 2>&1 201 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC3" table 113 prio 9993 202 | 203 | #VPN Client 4 204 | ip rule del fwmark "$FWMARK_OVPNC4" > /dev/null 2>&1 205 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC4" table 114 prio 9992 206 | 207 | #VPN Client 5 208 | ip rule del fwmark "$FWMARK_OVPNC5" > /dev/null 2>&1 209 | ip rule add from 0/0 fwmark "$FWMARK_OVPNC5" table 115 prio 9991 210 | 211 | ip route flush cache 212 | } 213 | 214 | ### Define interface/bitmask to route traffic to below 215 | set_fwmark_parms () { 216 | FWMARK_WAN="0x8000/0x8000" 217 | FWMARK_OVPNC1="0x1000/0x1000" 218 | FWMARK_OVPNC2="0x2000/0x2000" 219 | FWMARK_OVPNC3="0x4000/0x4000" 220 | FWMARK_OVPNC4="0x7000/0x7000" 221 | FWMARK_OVPNC5="0x3000/0x3000" 222 | } 223 | 224 | # route NETFLIX and AMAZONAWS traffic to WAN 225 | 226 | create_routing_rules () { 227 | iptables -t mangle -D PREROUTING -i br0 -m set --match-set x3mRouting_NETFLIX dst -j MARK --set-mark "$FWMARK_WAN" > /dev/null 2>&1 228 | iptables -t mangle -A PREROUTING -i br0 -m set --match-set x3mRouting_NETFLIX dst -j MARK --set-mark "$FWMARK_WAN" 229 | 230 | iptables -t mangle -D PREROUTING -i br0 -m set --match-set x3mRouting_AMAZONAWS dst -j MARK --set-mark "$FWMARK_WAN" > /dev/null 2>&1 231 | iptables -t mangle -A PREROUTING -i br0 -m set --match-set x3mRouting_AMAZONAWS dst -j MARK --set-mark "$FWMARK_WAN" 232 | } 233 | 234 | whitelist_ipinfo 235 | Chk_Entware 30 jq 236 | check_netflix_ipset_list_exist 237 | check_netflix_ipset_list_values 238 | check_amazonaws_ipset_list_exist 239 | check_amazonaws_ipset_list_values 240 | set_fwmark_parms 241 | create_fwmarks 242 | create_routing_rules 243 | } 244 | 245 | main 246 | logger -t "($(basename "$0"))" $$ Completed Script Execution 247 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project has been superceded by [x3mRouting ~ Selective Routing for Asuswrt-Merlin Firmware](https://github.com/Xentrk/x3mRouting). 2 | 3 | # netflix-vpn-bypass 4 | Selectively route Netflix traffic to the WAN interface, or one of the five OpenVPN clients, on **Asuswrt-Merlin** firmware. 5 | 6 | Since January 2016, Netflix blocks known VPN servers. This project was originally developed to bypass the OpenVPN client for Netflix traffic and route it to the WAN interface. The scripts now provide the ability to route Netflix traffic to an OpenVPN Client if desired. This can be accomplished by editing the $FWMARK parameter in the iptables commands inside the **create_routing_rules** function. If you want a VPN provider who can circumvent the Netflix VPN ban, see my blog post [Why I use Torguard as my VPN Provider](https://x3mtek.com/why-i-use-torguard-as-my-vpn-provider) to learn more. 7 | 8 | Netflix hosts on Amazon AWS servers. As a result, Amazon AWS domains in the US are also included. 9 | 10 | ### Overview 11 | 12 | There are two selective routing scripts used in this project. Each one uses a different method to collect the IPv4 addresses required for selective routing. Both scripts use the features of [IPSET](http://ipset.netfilter.org/) to collect IPv4 addresses in IPSET lists and match against the IPSET lists. 13 | 14 | **IPSET_Netflix.sh** collects the IPv4 addresses used by Netflix from https://ipinfo.io using the Autonomous System Number (ASN) assigned to Netflix. Amazon AWS supplies the list of IPv4 addresses in the json file at https://ip-ranges.amazonaws.com/ip-ranges.json 15 | 16 | Only the Amazon AWS US Regions are extracted from ip-ranges.json. As a result, the script will also route all Amazon AWS traffic bound for the US, including Amazon Prime traffic, to the WAN interface. 17 | 18 | **IPSET_Netflix_Domains.sh** uses the IPSET feature built into dnsmasq to dynamically generate the IPv4 address used by Netflix and Amazon AWS dynamically. This approach can be useful when your ISP is using the [Netflix Open Connect Network](https://media.netflix.com/en/company-blog/how-netflix-works-with-isps-around-the-globe-to-deliver-a-great-viewing-experience). 19 | 20 | #### Requirements 21 | 22 | 1. Installation of [entware]( https://github.com/RMerl/asuswrt-merlin/wiki/Entware). The **/opt/tmp** directory on entware is used to store the files containing the IPv4 addresses for the **IPSET_Netflix.sh** script and the backup IPSET list file for the **IPSET_Netflix_Domains.sh** script. 23 | 2. The entware package **jq** is required by the **IPSET_Netflix.sh** script. **jq** is a json file parser. To install **jq**, enter the command ```opkg install jq``` on the command line. 24 | 3. ipset version 6. To confirm the version you have installed, type ```ipset -v``` 25 | 4. OpenVPN Client Settings: 26 | - set **Redirect Internet traffic** to **Policy Rules** or **Policy Rules (Strict)** 27 | - dnsmasq is bypassed when **Accept DNS Configuration** is set to **Exclusive**. I recommend setting **Accept DNS Configuration** to **Strict** as a solution. In the **Custom Config** section, specify a DNS server of your choice using the command ```dhcp-option DNS xxx.xxx.xxx.xxx``` where the xxx's are a DNS server of your choice. For example: 28 | ```dhcp-option DNS 1.1.1.1``` 29 | 30 | ### IPSET_Netflix.sh 31 | Autonomous System Numbers (ASNs) are assigned to entities such as Internet Service Providers and other large organizations that control blocks of IP addresses. The ASN for Netflix is AS2906. 32 | 33 | This script will: 34 | 1. Create the IPSET lists x3mRouting_NETFLIX and x3mRouting_AMAZONAWS 35 | 2. Obtain the IPv4 addresses used by Netflix using AS2906 from ipinfo.io. 36 | 3. Add the Netflix IPv4 address to the IPSET list x3mRouting_NETFLIX 37 | 4. Parse the Amazon AWS json file using the jq entware package for IPv4 addresses used by Amazon in the US Region 38 | 5. Add the Amazon IPv4 address to the IPSET list x3mRouting_AMAZONAWS 39 | 6. Route IPv4 addresses in IPSET lists x3mRouting_NETFLIX and x3mRouting_AMAZONAWS to the WAN interface 40 | 41 | #### Installation 42 | 43 | /usr/sbin/curl --retry 3 "https://raw.githubusercontent.com/Xentrk/netflix-vpn-bypass/master/IPSET_Netflix.sh" -o /jffs/scripts/IPSET_Netflix.sh && chmod 755 /jffs/scripts/IPSET_Netflix.sh 44 | 45 | If the script runs successfully, you can have the script execute at system start-up by calling it from **/jffs/scripts/nat-start** by including the line ```sh /jffs/scripts/IPSET_Netflix.sh``` in the file. Make sure **nat-start** has a she-bang as the first line in the file ```#!/bin/sh``` and is executable e.g. ```chmod 755 /jffs/scripts/nat-start```. 46 | 47 | ### IPSET_Netflix_Domains.sh 48 | **IPSET_Netflix_Domains.sh** uses the feature of ipset in dnsmasq to dynamically generate the IPv4 address used by Netflix and Amazon AWS dynamically. The script will create a cron job that will backup the IPSET list at 2:00 am. The backup will be used to restore the IPSET list upon system startup. 49 | 50 | This approach can be useful when your ISP is using the [Netflix Open Connect Network](https://media.netflix.com/en/company-blog/how-netflix-works-with-isps-around-the-globe-to-deliver-a-great-viewing-experience). The domain names used may vary by region. As a result, you will have to do some analysis to determine the domain names Netflix is using if the domains included in the script do not work for you. Below are the list of domain names used in the script. 51 | 52 | ipset=/amazonaws.com/netflix.com/nflxext.com/nflximg.net/nflxso.net/nflxvideo.net/x3mRouting_NETFLIX_DNSMASQ 53 | 54 | The **x3mRouting_NETFLIX_DNSMASQ** entry is the name of the IPSET list. The script will place the line in **/jffs/configs/dnsmasq.conf.add** if it does not exist. 55 | 56 | #### getdomainnames.sh 57 | To determine the domain names, follow the installation instructions at the end of this section to download the script **getdomainnames.sh** to **/jffs/scripts**. Navigate to the dnsmasq log file directory. If you have entware installed, the dnsmasq.log file location is **/opt/var/log**. 58 | 59 | Turn off the OpenVPN Client so all of your network traffic will traverse thru the WAN. Navigate to the dnsmasq log file directory **/opt/var/log**. Type the command to start capturing domains used by Netflix: 60 | 61 | tail -f dnsmasq.log > Netflix 62 | 63 | Now, go to the device you are watching Netflix from. If you are streaming from your PC or laptop, close out other applications to minimize collecting domain names for non-Netflix traffic. Navigate around the Netflix menu options and watch several videos for a few minutes each to generate traffic and log entries to dnsmasq.log. 64 | 65 | When done generating Netflix traffic, press **ctrl-C** to stop logging to the **/opt/var/log/Netflix** file. Run the **getdomainnames.sh** script, passing the **file name** and **IP address** of the device you were watching Netflix from. For example: 66 | 67 | . /jffs/scripts/getdomainnames.sh Netflix 192.168.1.20 68 | 69 | This will create a file called **Netflix_domains** in the **/opt/var/log** directory. Open the file in an editor to view the domains names collected when watching Netflix. The next step is to desk check the file for domains not related to Netflix. These are domains generated by other applications on the LAN client you streamed Netflix from. Once you have narrowed down the domains, the next step is to update the **ipset=** references in the **IPSET_Netflix_Domains.sh** script using the domain names you captured. However, do not use the fully qualified domain name. For example, the domain **occ-0-1077-1062.1.nflxso.net** would be entered as **nflxso.net**; Likewise, www.netflix.com would be entered as **netflix.com**. **IPSET_Netflix_Domains.sh** will copy the **ipset=/** line to **/jffs/configs/dnsmasq.conf.add** 70 | 71 | The ```nslookup ``` command is useful in looking up IPv4 addresses associated with a domain. Once you have the IPv4 address, you can use the ```whob ``` command to display more information about the domain to confirm if it is associated with Netflix, Amazon AWS or a CDN provider, such as Akamai. **whob** is an entware package. Install using the command ```opkg install whob``` 72 | 73 | # nslookup occ-0-1077-1062.1.nflxso.net 74 | 75 | Server: 127.0.0.1 76 | Address 1: 127.0.0.1 localhost.localdomain 77 | 78 | Name: occ-0-1077-1062.1.nflxso.net 79 | Address 1: 2a00:86c0:600:96::138 ipv6_1.lagg0.c009.lax004.ix.nflxvideo.net 80 | Address 3: 198.38.96.132 ipv4_1.lagg0.c003.lax004.ix.nflxvideo.net 81 | 82 | # whob 198.38.96.147 83 | 84 | IP: 198.38.96.147 85 | Origin-AS: 2906 86 | Prefix: 198.38.96.0/24 87 | AS-Path: 18106 4657 6762 2906 88 | AS-Org-Name: Netflix Streaming Services Inc. 89 | Org-Name: Netflix Streaming Services Inc. 90 | Net-Name: SSI-CDN-2 91 | Cache-Date: 1536245423 92 | Latitude: 39.738008 93 | Longitude: -75.550353 94 | City: Wilmington 95 | Region: Delaware 96 | Country: United States 97 | Country-Code: US 98 | 99 | #### Installation 100 | /usr/sbin/curl --retry 3 "https://raw.githubusercontent.com/Xentrk/netflix-vpn-bypass/master/getdomainnames.sh" -o /jffs/scripts/getdomainnames.sh && chmod 755 /jffs/scripts/getdomainnames.sh 101 | 102 | /usr/sbin/curl --retry 3 "https://raw.githubusercontent.com/Xentrk/netflix-vpn-bypass/master/IPSET_Netflix_Domains.sh" -o /jffs/scripts/IPSET_Netflix_Domains.sh && chmod 755 /jffs/scripts/IPSET_Netflix_Domains.sh 103 | 104 | ### Troubleshooting 105 | ```ipset -L x3mRouting_NETFLIX``` command will list the contents of the IPSET list x3mRouting_NETFLIX 106 | 107 | ```iptables -nvL PREROUTING -t mangle --line``` will display the PREROUTING Chain statistics or packet information. This command is very helpful to validate if traffic is traversing the chain. 108 | 109 | ```ip rule``` will display the rules and priorities for the LAN clients and the fwmark/bitmask created for the WAN and OpenVPN interfaces. 110 | 111 | ```service restart_dnsmasq``` will restart dnsmasq. Run this command to restart dnsmasq after making changes to **/jffs/configs/dnsmasq.conf.add**. 112 | 113 | ### Collaborators 114 | This project uses the selective routing method espoused by [Martineau](https://www.snbforums.com/members/martineau.13215/) on [snbforums.com](https://www.snbforums.com/forums/). His technical assistance and support helped to make this project possible. [Martineau](https://www.snbforums.com/members/martineau.13215/) also provided the **Chk_Entware** function. 115 | 116 | ### Support 117 | Support for the project is available on [snbforums.com](https://www.snbforums.com/threads/selective-routing-for-netflix.42661/) 118 | --------------------------------------------------------------------------------