├── README.md ├── Manual Install - MacOS - FreshJR QOS.command ├── Manual Install - Windows - FreshJR QOS.bat ├── FreshJR_QoS_Stats.asp └── FreshJR_QOS.sh /README.md: -------------------------------------------------------------------------------- 1 | # FreshJR QOS - Modification Script for AdaptiveQOS on Asus Routers 2 | 3 | This script has been tested on ASUS AC-68U, running RMerlin FW 384.4, using Adaptive QOS with Manual Bandwidth Settings 4 | 5 | ## Quick Overview: 6 | 7 | -- Script Changes Unidentified Packet QOS destination from "Default" Traffic Container (Category7) into user definable (in WebUI) "Others" Traffic Container 8 | 9 | -- Script Changes Minimum Guaranteed Bandwidth per QOS category from 128Kbit into user defined percentages upload and download. 10 | 11 | -- Script allows for custom QOS rules 12 | 13 | -- Script allows for redirection of existing identified traffic 14 | 15 | ## Full Overview: 16 | 17 | See SmallNetBuilder for more information & discussion 18 | 19 | ## Installation: 20 | 21 | In your SSH Client: 22 | 23 | ``` curl "https://raw.githubusercontent.com/FreshPr/FreshJR_QOS/master/FreshJR_QOS.sh" -o /jffs/scripts/FreshJR_QOS --create-dirs && sh /jffs/scripts/FreshJR_QOS -install ``` 24 | 25 | ## Uninstall: 26 | 27 | In your SSH Client: 28 | 29 | ``` /jffs/scripts/FreshJR_QOS -uninstall ``` 30 | -------------------------------------------------------------------------------- /Manual Install - MacOS - FreshJR QOS.command: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd "$(dirname "${0}")" 3 | clear && printf '\e[3J' 4 | echo "-------------------------------------------------" 5 | echo "---- Ctrl + C to quit installer at any time ----" 6 | echo "-------------------------------------------------" 7 | echo "" 8 | 9 | echo "Detecting if files are present in current folder" 10 | echo "" 11 | file=1 12 | if [ -e "./FreshJR_QOS.sh" ] ; then 13 | echo " [x] FreshJR_QOS.sh" 14 | else 15 | echo " [ ] FreshJR_QOS.sh" 16 | file=0 17 | fi 18 | 19 | if [ -e "./FreshJR_QoS_Stats.asp" ] ; then 20 | echo " [x] FreshJR_QoS_Stats" 21 | else 22 | echo " [ ] FreshJR_QoS_Stats" 23 | file=0 24 | fi 25 | 26 | echo "" 27 | 28 | if [ "${file}" -eq 0 ] ; then 29 | echo "Not all files detected" 30 | echo "--CANNOT CONTINUE!!--" 31 | echo "" 32 | read -n 1 -s -r -p "(Press any key to Exit)" 33 | echo "" 34 | echo "" 35 | exit 36 | fi 37 | 38 | echo "Getting router login information" 39 | echo"" 40 | read -p " Router ipaddress: " ip 41 | read -p " Router username: " user 42 | echo " Router password: " 43 | echo " (entry will appear blank - required twice)" 44 | echo "" 45 | 46 | echo "Transferring files onto router " 47 | scp "./FreshJR_QOS.sh" "./FreshJR_QoS_Stats.asp" "${user}"@"${ip}":/jffs/ 48 | echo "" 49 | 50 | echo "Starting script installer" 51 | ssh -t -o LogLevel=quiet -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${user}"@"${ip}" ' 52 | mkdir /jffs/scripts/ 2> /dev/null; 53 | mv /jffs/FreshJR_QOS.sh /jffs/scripts/FreshJR_QOS; 54 | cat /jffs/FreshJR_QoS_Stats.asp > /jffs/scripts/www_FreshJR_QoS_Stats.asp; 55 | rm /jffs/FreshJR_QoS_Stats.asp 56 | dos2unix /jffs/scripts/FreshJR_QOS 57 | sh /jffs/scripts/FreshJR_QOS -install;' 58 | 59 | read -n 1 -s -r -p "(Press any key to Exit)" 60 | echo "" 61 | echo "" 62 | exit -------------------------------------------------------------------------------- /Manual Install - Windows - FreshJR QOS.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal EnableDelayedExpansion 3 | 4 | REM --------DETECT FILES------------ 5 | 6 | set putty=0 7 | set pscp=0 8 | set script=0 9 | set webpage=0 10 | 11 | set "putty_path=-" 12 | set "pscp_path=-" 13 | set "script_path=-" 14 | set "webpage_path=-" 15 | 16 | if exist "!cd!\putty.exe" ( 17 | set putty=1 18 | set "putty_path=!cd!\putty.exe" 19 | ) 20 | if exist "!cd!\pscp.exe" ( 21 | set pscp=1 22 | set "pscp_path=!cd!\pscp.exe" 23 | ) 24 | if exist "!cd!\FreshJR_QOS.sh" ( 25 | set script=1 26 | set "script_path=!cd!\FreshJR_QOS.sh" 27 | echo !script_path! 28 | ) 29 | if exist "!cd!\FreshJR_QoS_Stats.asp" ( 30 | set webpage=1 31 | set "webpage_path=!cd!\FreshJR_QoS_Stats.asp" 32 | ) 33 | 34 | set /a "files=!putty!+!pscp!+!script!+!webpage!" 35 | set /a "exectuables=!putty!+!pscp!" 36 | 37 | REM --------OUTPUT FILE DETECTION------------ 38 | 39 | cls 40 | echo Detecting if files are present in current folder 41 | echo: 42 | if !script!==1 ( 43 | echo [x] FreshJR_QOS.sh !script_path! 44 | ) else ( 45 | echo [ ] FreshJR_QOS.sh !cd!\FreshJR_QOS.sh NOT detected 46 | ) 47 | if !webpage!==1 ( 48 | echo [x] FreshJR_QoS_Stats.asp !webpage_path! 49 | ) else ( 50 | echo [ ] FreshJR_QoS_Stats.asp !cd!\FreshJR_QoS_Stats.asp NOT detected 51 | ) 52 | if !putty!==1 ( 53 | echo [x] putty.exe !putty_path! 54 | ) else ( 55 | echo [ ] putty.exe !cd!\putty.exe NOT detected 56 | ) 57 | 58 | if !pscp!==1 ( 59 | echo [x] pscp.exe !pscp_path! 60 | ) else ( 61 | echo [ ] pscp.exe !cd!\pscp.exe NOT detected 62 | ) 63 | 64 | echo: 65 | 66 | if not !files!==4 ( 67 | echo Not all files detected 68 | echo --CANNOT CONTINUE^!^!-- 69 | echo: 70 | if not !exectuables!==2 ( 71 | echo -------------------------------------------------------------------------- 72 | echo Putty / Pscp portable BINARY FILES are located at the following link: 73 | echo: 74 | echo https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 75 | echo --------------------------------------------------------------------------- 76 | echo: 77 | ) 78 | pause 79 | exit 80 | ) 81 | 82 | if exist "!cd!\scripts\" ( 83 | echo Remove the folder "scripts" in current directory 84 | echo --CANNOT CONTINUE^!^!-- 85 | echo: 86 | pause 87 | exit 88 | ) 89 | 90 | if exist "!cd!\ssh_command" ( 91 | echo Remove the file "ssh_command" in current directory 92 | echo --CANNOT CONTINUE^!^!-- 93 | echo: 94 | pause 95 | exit 96 | ) 97 | 98 | REM --------PROMPT USER INPUT------------ 99 | 100 | echo Getting router login information 101 | echo: 102 | set /p "user=. Router username: " 103 | set /p "pass=. Router password: " 104 | set /p " ip=. Router ipaddress: " 105 | echo: 106 | 107 | echo Transferring files onto the router 108 | echo: 109 | mkdir "!cd!\scripts\" 110 | pscp -r -pw !pass! -scp "!cd!\scripts" !user!@!ip!:/jffs/ 111 | rmdir "!cd!\scripts\" 112 | pscp -pw !pass! -scp "!webpage_path!" !user!@!ip!:/jffs/scripts/www_FreshJR_QoS_Stats.asp 113 | pscp -pw !pass! -scp "!script_path!" !user!@!ip!:/jffs/scripts/FreshJR_QOS 114 | echo: 115 | echo Starting script installer 116 | echo: 117 | echo dos2unix /jffs/scripts/FreshJR_QOS ^&^& sh /jffs/scripts/FreshJR_QOS -install ^&^& read -n 1 -s -r -p "(Press any key to Exit)" > ssh_command 118 | putty.exe -ssh !user!@!ip! -pw !pass! -m "!cd!\ssh_command" -t 119 | del "!cd!\ssh_command" 120 | 121 | pause 122 | -------------------------------------------------------------------------------- /FreshJR_QoS_Stats.asp: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | QoS - Classification 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 135 | 139 | 1499 | 1500 | 1501 |
1502 | 1503 | 1504 |
1505 | "> 1506 | "> 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1522 | 1993 | 1994 | 1995 |
  1519 | 1520 | 1521 | 1523 | 1524 | 1525 | 1526 | 1990 | 1991 |
1527 | 1528 | 1529 | 1530 | 1986 | 1987 | 1988 |
1531 |
Traffic classification
1532 |
FreshJR Mod (Customize)
1533 |
1534 | 1535 | 1536 | 1914 | 1915 | 1916 | 1917 | 1918 | 1926 | 1927 |
Automatically refresh data every 1919 | 1925 |
1928 |
1929 | 1930 | 1931 | 1932 | 1933 | 1934 | 1938 | 1939 | 1940 | 1941 | 1942 | 1943 | 1944 | 1948 | 1949 | 1950 |
1935 |
Download
1936 | 1937 |
 
1945 |
Upload
1946 | 1947 |
1951 |
1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1962 | 1963 | 1964 |
Filter By Device: 1958 | 1961 |
1965 | 1966 | 1967 | 1968 | 1969 | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 |
Tracked connections
ProtoSourceSPortDestinationDPortApplication
1983 | 1984 | 1985 |
1989 |
1992 |
 
1996 |
1997 | 1998 | 1999 | -------------------------------------------------------------------------------- /FreshJR_QOS.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ##FreshJR_QOS 3 | version=8.8 4 | release=03/07/2019 5 | #Copyright (C) 2017-2019 FreshJR - All Rights Reserved 6 | #Tested with ASUS AC-68U, FW384.9, using Adaptive QOS with Manual Bandwidth Settings 7 | # Script Changes Unidentified traffic destination away from "Defaults" into "Others" 8 | # Script Changes HTTPS traffic destination away from "Net Control" into "Web Surfing" 9 | # Script Changes Guaranteed Bandwidth per QOS category into logical percentages of upload and download. 10 | # Script Repurposes "Defaults" to contain "Game Downloads" 11 | # "Game Downloads" moved into 6th position 12 | # "Lowest Defined" moved into 7th position 13 | #Script includes misc hardcoded rules 14 | # (Wifi Calling) - UDP traffic on remote ports 500 & 4500 moved into VOIP 15 | # (Facetime) - UDP traffic on local ports 16384 - 16415 moved into VOIP 16 | # (Usenet) - TCP traffic on remote ports 119 & 563 moved into Downloads 17 | # (Gaming) - Gaming TCP traffic from remote ports 80 & 443 moved into Game Downloads. 18 | # (Snapchat) - Moved into Others 19 | # (Speedtest.net) - Moved into Downloads 20 | # (Google Play) - Moved into Downloads 21 | # (Apple AppStore)- Moved into Downloads 22 | # (Advertisement) - Moved into Downloads 23 | # (VPN Fix) - Router VPN Client upload traffic moved into Downloads instead of whitelisted 24 | # (VPN Fix) - Router VPN Client download traffic moved into Downloads instead of showing up in Uploads 25 | # (Gaming Manual) - Unidentified traffic for specified devices, not originating from ports 80/443, moved into "Gaming" 26 | # 27 | # Gaming traffic originating from ports 80 & 443 is primarily downloads & patches (some lobby/login protocols mixed within) 28 | # Manually configurable rule will take untracked traffic, not originating from 80/443, for specified devices and place it into Gaming 29 | # Use of this gaming rule REQUIRES devices to have a continuous static ip assignment && this range needs to be defined in the script 30 | # 31 | # Custom rules can be created within the WebUI OR by running the -rules command: 32 | # (custom rules): /jffs/scripts/FreshJR_QOS -rules 33 | # 34 | # Default bandwidth allocation per category can be adjusted via WebUI OR -rates command: 35 | # (custom rates): /jffs/scripts/FreshJR_QOS -rates 36 | # 37 | ##For discussion visit this thread: 38 | ## https://www.snbforums.com/threads/release-freshjr-adaptive-qos-improvements-custom-rules-and-inner-workings.36836/ 39 | ## https://github.com/FreshJR07/FreshJR_QOS (Source Code + Backup Link) 40 | # 41 | ##License 42 | ## FreshJR_QOS is free to use under the GNU General Public License, version 3 (GPL-3.0). 43 | ## https://opensource.org/licenses/GPL-3.0 44 | 45 | #################### MODIFY BELOW WITH CAUTION ##################### 46 | #################### MODIFY BELOW WITH CAUTION ##################### 47 | # 48 | ### IF YOU MANUALLY ADD RULES TO AREA BELOW THEN KEEP IN MIND THAT YOUR CHANGES WILL TAKE EFFECT BUT WILL NOT BE REFLECTED UNDER THE TRACKED CONNECTIONS SECTION OF THE WEBUI. 49 | ### FOR HARDCODED CHANGES TO BE REFLECTED IN TRACKED CONNECTIONS SECTION OF THE WEBUI THEN YOU ALSO HAVE TO MODIFY THE CORRESPONDING JAVASCRIPT CODE IN /jffs/scripts/FreshJR_QoS_Stats.asp 50 | ### INSTEAD OF HARDCODED CHANGES (legacy method) YOU CAN USE THE SCRIPTS -RULES COMMAND OR ENTER THE WEBUI PAGE FOR CREATING RULES AND THOSE CHANGES WILL BE REFLECTED IN THE TRACKED CONNECTIONS TABLE. 51 | # 52 | #################### MODIFY BELOW WITH CAUTION ##################### 53 | #################### MODIFY BELOW WITH CAUTION ##################### 54 | 55 | iptable_down_rules() { 56 | echo "Applying - Iptable Down Rules" 57 | ##DOWNLOAD (INCOMMING TRAFFIC) CUSTOM RULES START HERE -- legacy method 58 | 59 | iptables -D POSTROUTING -t mangle -o br0 -p udp -m multiport --sports 500,4500 -j MARK --set-mark ${VOIP_mark_down} &> /dev/null #Wifi Calling - (All incoming traffic from WAN source ports 500 & 4500 --> VOIP ) 60 | iptables -A POSTROUTING -t mangle -o br0 -p udp -m multiport --sports 500,4500 -j MARK --set-mark ${VOIP_mark_down} 61 | 62 | iptables -D POSTROUTING -t mangle -o br0 -p udp --dport 16384:16415 -j MARK --set-mark ${VOIP_mark_down} &> /dev/null #Facetime - (All incoming traffic to LAN destination ports 16384-16415 --> VOIP ) 63 | iptables -A POSTROUTING -t mangle -o br0 -p udp --dport 16384:16415 -j MARK --set-mark ${VOIP_mark_down} 64 | 65 | iptables -D POSTROUTING -t mangle -o br0 -p tcp -m multiport --sports 119,563 -j MARK --set-mark ${Downloads_mark_down} &> /dev/null #Usenet - (All incoming traffic from WAN source ports 119 & 563 --> Downloads ) 66 | iptables -A POSTROUTING -t mangle -o br0 -p tcp -m multiport --sports 119,563 -j MARK --set-mark ${Downloads_mark_down} 67 | 68 | iptables -D POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000 &> /dev/null #VPN Fix - (Fixes download traffic showing up in upload section when router is acting as a VPN Client) 69 | iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000 70 | 71 | iptables -D POSTROUTING -t mangle -o br0 -m mark --mark 0x80080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_down} &> /dev/null #Gaming - (Incoming "Gaming" traffic from WAN source ports 80 & 443 --> Defaults//GameDownloads) 72 | iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x80080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_down} 73 | 74 | ##DOWNLOAD (INCOMMING TRAFFIC) CUSTOM RULES END HERE -- legacy method 75 | 76 | if [ "$( echo $gameCIDR | tr -cd '.' | wc -c )" -eq "3" ] ; then 77 | iptables -D POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p tcp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down} &> /dev/null #Gaming - (Incoming "Unidentified" TCP traffic, for devices specified, not from WAN source ports 80 & 443 --> Gaming) 78 | iptables -A POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p tcp -m multiport ! --sports 80,433 -j MARK --set-mark ${Gaming_mark_down} 79 | 80 | iptables -D POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p udp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down} &> /dev/null #Gaming - (Incoming "Unidentified" UDP traffic, for devices specified, not from WAN source ports 80 & 443 --> Gaming) 81 | iptables -A POSTROUTING -t mangle -o br0 -d $gameCIDR -m mark --mark 0x80000000/0x8000ffff -p udp -m multiport ! --sports 80,443 -j MARK --set-mark ${Gaming_mark_down} 82 | fi 83 | 84 | if ! [ -z "$ip1_down" ] ; then #Script Interactively Defined Rule 1 85 | if [ "$(echo ${ip1_down} | grep -c "both")" -ge "1" ] ; then 86 | iptables -D POSTROUTING -t mangle -o br0 ${ip1_down//both/tcp} &> /dev/null 87 | iptables -A POSTROUTING -t mangle -o br0 ${ip1_down//both/tcp} 88 | iptables -D POSTROUTING -t mangle -o br0 ${ip1_down//both/udp} &> /dev/null 89 | iptables -A POSTROUTING -t mangle -o br0 ${ip1_down//both/udp} 90 | else 91 | iptables -D POSTROUTING -t mangle -o br0 ${ip1_down} &> /dev/null 92 | iptables -A POSTROUTING -t mangle -o br0 ${ip1_down} 93 | fi 94 | fi 95 | 96 | if ! [ -z "$ip2_down" ] ; then #Script Interactively Defined Rule 2 97 | if [ "$(echo ${ip2_down} | grep -c "both")" -ge "1" ] ; then 98 | iptables -D POSTROUTING -t mangle -o br0 ${ip2_down//both/tcp} &> /dev/null 99 | iptables -A POSTROUTING -t mangle -o br0 ${ip2_down//both/tcp} 100 | iptables -D POSTROUTING -t mangle -o br0 ${ip2_down//both/udp} &> /dev/null 101 | iptables -A POSTROUTING -t mangle -o br0 ${ip2_down//both/udp} 102 | else 103 | iptables -D POSTROUTING -t mangle -o br0 ${ip2_down} &> /dev/null 104 | iptables -A POSTROUTING -t mangle -o br0 ${ip2_down} 105 | fi 106 | fi 107 | 108 | if ! [ -z "$ip3_down" ] ; then #Script Interactively Defined Rule 3 109 | if [ "$(echo ${ip3_down} | grep -c "both")" -ge "1" ] ; then 110 | iptables -D POSTROUTING -t mangle -o br0 ${ip3_down//both/tcp} &> /dev/null 111 | iptables -A POSTROUTING -t mangle -o br0 ${ip3_down//both/tcp} 112 | iptables -D POSTROUTING -t mangle -o br0 ${ip3_down//both/udp} &> /dev/null 113 | iptables -A POSTROUTING -t mangle -o br0 ${ip3_down//both/udp} 114 | else 115 | iptables -D POSTROUTING -t mangle -o br0 ${ip3_down} &> /dev/null 116 | iptables -A POSTROUTING -t mangle -o br0 ${ip3_down} 117 | fi 118 | fi 119 | 120 | if ! [ -z "$ip4_down" ] ; then #Script Interactively Defined Rule 4 121 | if [ "$(echo ${ip4_down} | grep -c "both")" -ge "1" ] ; then 122 | iptables -D POSTROUTING -t mangle -o br0 ${ip4_down//both/tcp} &> /dev/null 123 | iptables -A POSTROUTING -t mangle -o br0 ${ip4_down//both/tcp} 124 | iptables -D POSTROUTING -t mangle -o br0 ${ip4_down//both/udp} &> /dev/null 125 | iptables -A POSTROUTING -t mangle -o br0 ${ip4_down//both/udp} 126 | else 127 | iptables -D POSTROUTING -t mangle -o br0 ${ip4_down} &> /dev/null 128 | iptables -A POSTROUTING -t mangle -o br0 ${ip4_down} 129 | fi 130 | fi 131 | } 132 | 133 | iptable_up_rules(){ 134 | 135 | #wan="ppp0" ## WAN interface over-ride for upload traffic if automatic detection is not working properly 136 | 137 | echo "Applying - Iptable Up Rules ($wan)" 138 | 139 | ##UPLOAD (OUTGOING TRAFFIC) CUSTOM RULES START HERE -- legacy method 140 | 141 | iptables -D POSTROUTING -t mangle -o $wan -p udp -m multiport --dports 500,4500 -j MARK --set-mark ${VOIP_mark_up} &> /dev/null #Wifi Calling - (All outgoing traffic to WAN destination ports 500 & 4500 --> VOIP ) 142 | iptables -A POSTROUTING -t mangle -o $wan -p udp -m multiport --dports 500,4500 -j MARK --set-mark ${VOIP_mark_up} 143 | 144 | iptables -D POSTROUTING -t mangle -o $wan -p udp --sport 16384:16415 -j MARK --set-mark ${VOIP_mark_up} &> /dev/null #Facetime - (All outgoing traffic from LAN source ports 16384-16415 --> VOIP ) 145 | iptables -A POSTROUTING -t mangle -o $wan -p udp --sport 16384:16415 -j MARK --set-mark ${VOIP_mark_up} 146 | 147 | iptables -D POSTROUTING -t mangle -o $wan -p tcp -m multiport --dports 119,563 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #Usenet - (All outgoing traffic to WAN destination ports 119 & 563 --> Downloads ) 148 | iptables -A POSTROUTING -t mangle -o $wan -p tcp -m multiport --dports 119,563 -j MARK --set-mark ${Downloads_mark_up} 149 | 150 | iptables -D OUTPUT -t mangle -o $wan -p udp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #VPN Fix - (Fixes upload traffic not detected when the router is acting as a VPN Client) 151 | iptables -A OUTPUT -t mangle -o $wan -p udp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} 152 | 153 | iptables -D OUTPUT -t mangle -o $wan -p tcp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} &> /dev/null #VPN Fix - (Fixes upload traffic not detected when the router is acting as a VPN Client) 154 | iptables -A OUTPUT -t mangle -o $wan -p tcp -m multiport ! --dports 53,123 -j MARK --set-mark ${Downloads_mark_up} 155 | 156 | iptables -D POSTROUTING -t mangle -o $wan -m mark --mark 0x40080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_up} &> /dev/null #Gaming - (Outgoing "Gaming" traffic to WAN destinations ports 80 & 443 --> Defaults//GameDownloads) 157 | iptables -A POSTROUTING -t mangle -o $wan -m mark --mark 0x40080000/0xc03f0000 -p tcp -m multiport --sports 80,443 -j MARK --set-mark ${Default_mark_up} 158 | 159 | ##UPLOAD (OUTGOING TRAFFIC) CUSTOM RULES END HERE -- legacy method 160 | 161 | if [ "$( echo $gameCIDR | tr -cd '.' | wc -c )" -eq "3" ] ; then 162 | iptables -D POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p tcp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} &> /dev/null #Gaming - (Outgoing "Unidentified" TCP traffic, for devices specified, not to WAN destination ports 80 & 443 --> Gaming) 163 | iptables -A POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p tcp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} 164 | 165 | iptables -D POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p udp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} &> /dev/null #Gaming - (Outgoing "Unidentified" UDP traffic, for devices specified, not to WAN destination ports 80 & 443 --> Gaming) 166 | iptables -A POSTROUTING -t mangle -o $wan -s $gameCIDR -m mark --mark 0x40000000/0x4000ffff -p udp -m multiport ! --dports 80,443 -j MARK --set-mark ${Gaming_mark_up} 167 | fi 168 | 169 | if ! [ -z "$ip1_up" ] ; then #Script Interactively Defined Rule 1 170 | if [ "$(echo ${ip1_up} | grep -c "both")" -ge "1" ] ; then 171 | iptables -D POSTROUTING -t mangle -o $wan ${ip1_up//both/tcp} &> /dev/null 172 | iptables -A POSTROUTING -t mangle -o $wan ${ip1_up//both/tcp} 173 | iptables -D POSTROUTING -t mangle -o $wan ${ip1_up//both/udp} &> /dev/null 174 | iptables -A POSTROUTING -t mangle -o $wan ${ip1_up//both/udp} 175 | else 176 | iptables -D POSTROUTING -t mangle -o $wan ${ip1_up} &> /dev/null 177 | iptables -A POSTROUTING -t mangle -o $wan ${ip1_up} 178 | fi 179 | fi 180 | 181 | if ! [ -z "$ip2_up" ] ; then #Script Interactively Defined Rule 2 182 | if [ "$(echo ${ip2_up} | grep -c "both")" -ge "1" ] ; then 183 | iptables -D POSTROUTING -t mangle -o $wan ${ip2_up//both/tcp} &> /dev/null 184 | iptables -A POSTROUTING -t mangle -o $wan ${ip2_up//both/tcp} 185 | iptables -D POSTROUTING -t mangle -o $wan ${ip2_up//both/udp} &> /dev/null 186 | iptables -A POSTROUTING -t mangle -o $wan ${ip2_up//both/udp} 187 | else 188 | iptables -D POSTROUTING -t mangle -o $wan ${ip2_up} &> /dev/null 189 | iptables -A POSTROUTING -t mangle -o $wan ${ip2_up} 190 | fi 191 | fi 192 | 193 | if ! [ -z "$ip3_up" ] ; then #Script Interactively Defined Rule 3 194 | if [ "$(echo ${ip3_up} | grep -c "both")" -ge "1" ] ; then 195 | iptables -D POSTROUTING -t mangle -o $wan ${ip3_up//both/tcp} &> /dev/null 196 | iptables -A POSTROUTING -t mangle -o $wan ${ip3_up//both/tcp} 197 | iptables -D POSTROUTING -t mangle -o $wan ${ip3_up//both/udp} &> /dev/null 198 | iptables -A POSTROUTING -t mangle -o $wan ${ip3_up//both/udp} 199 | else 200 | iptables -D POSTROUTING -t mangle -o $wan ${ip3_up} &> /dev/null 201 | iptables -A POSTROUTING -t mangle -o $wan ${ip3_up} 202 | fi 203 | fi 204 | 205 | if ! [ -z "$ip4_up" ] ; then #Script Interactively Defined Rule 4 206 | if [ "$(echo ${ip4_up} | grep -c "both")" -ge "1" ] ; then 207 | iptables -D POSTROUTING -t mangle -o $wan ${ip4_up//both/tcp} &> /dev/null 208 | iptables -A POSTROUTING -t mangle -o $wan ${ip4_up//both/tcp} 209 | iptables -D POSTROUTING -t mangle -o $wan ${ip4_up//both/udp} &> /dev/null 210 | iptables -A POSTROUTING -t mangle -o $wan ${ip4_up//both/udp} 211 | else 212 | iptables -D POSTROUTING -t mangle -o $wan ${ip4_up} &> /dev/null 213 | iptables -A POSTROUTING -t mangle -o $wan ${ip4_up} 214 | fi 215 | fi 216 | } 217 | 218 | tc_redirection_down_rules() { 219 | echo "Applying TC Down Rules" 220 | ${tc} filter del dev br0 parent 1: prio $1 #remove original unidentified traffic rule 221 | ${tc} filter del dev br0 parent 1: prio 22 &> /dev/null #remove original HTTPS rule 222 | ${tc} filter del dev br0 parent 1: prio 23 &> /dev/null #remove original HTTPS rule 223 | ! [ -z "$tc4_down" ] && ${tc} filter add dev br0 protocol all ${tc4_down} #Script Interactively Defined Rule 4 224 | ! [ -z "$tc3_down" ] && ${tc} filter add dev br0 protocol all ${tc3_down} #Script Interactively Defined Rule 3 225 | ! [ -z "$tc2_down" ] && ${tc} filter add dev br0 protocol all ${tc2_down} #Script Interactively Defined Rule 2 226 | ! [ -z "$tc1_down" ] && ${tc} filter add dev br0 protocol all ${tc1_down} #Script Interactively Defined Rule 1 227 | ${tc} filter add dev br0 protocol all prio 20 u32 match mark 0x8012003F 0xc03fffff flowid ${Web} # HTTP rule with different destination 228 | ${tc} filter add dev br0 protocol all prio 22 u32 match mark 0x80130000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination 229 | ${tc} filter add dev br0 protocol all prio 23 u32 match mark 0x80140000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination 230 | ##DOWNLOAD APP_DB TRAFFIC REDIRECTION RULES START HERE -- legacy method 231 | 232 | ${tc} filter add dev br0 protocol all prio 2 u32 match mark 0x8000006B 0xc03fffff flowid ${Others} #Snapchat 233 | ${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D0007 0xc03fffff flowid ${Downloads} #Speedtest.net 234 | ${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D0086 0xc03fffff flowid ${Downloads} #Google Play 235 | ${tc} filter add dev br0 protocol all prio 15 u32 match mark 0x800D00A0 0xc03fffff flowid ${Downloads} #Apple AppStore 236 | ${tc} filter add dev br0 protocol all prio 50 u32 match mark 0x801A0000 0xc03f0000 flowid ${Downloads} #Advertisement 237 | 238 | ##DOWNLOAD APP_DB TRAFFIC REDIRECTION RULES END HERE -- legacy method 239 | 240 | ${tc} filter add dev br0 protocol all prio $1 u32 match mark 0x80000000 0x8000ffff flowid ${Others} #recreate unidentified traffic rule with different destination - Routes Unidentified Traffic into webUI adjustable "Others" traffic container instead of "Defaults" 241 | ${tc} filter add dev br0 protocol all prio 10 u32 match mark 0x803f0001 0xc03fffff flowid ${Defaults} #Used for iptables Default_mark_down functionality 242 | } 243 | 244 | tc_redirection_up_rules() { 245 | echo "Applying TC Up Rules" 246 | ${tc} filter del dev eth0 parent 1: prio $1 #remove original unidentified traffic rule 247 | ${tc} filter del dev eth0 parent 1: prio 22 &> /dev/null #remove original HTTPS rule 248 | ${tc} filter del dev eth0 parent 1: prio 23 &> /dev/null #remove original HTTPS rule 249 | ! [ -z "$tc4_up" ] && ${tc} filter add dev eth0 protocol all ${tc4_up} #Script Interactively Defined Rule 4 250 | ! [ -z "$tc3_up" ] && ${tc} filter add dev eth0 protocol all ${tc3_up} #Script Interactively Defined Rule 3 251 | ! [ -z "$tc2_up" ] && ${tc} filter add dev eth0 protocol all ${tc2_up} #Script Interactively Defined Rule 2 252 | ! [ -z "$tc1_up" ] && ${tc} filter add dev eth0 protocol all ${tc1_up} #Script Interactively Defined Rule 1 253 | ${tc} filter add dev eth0 protocol all prio 20 u32 match mark 0x4012003F 0xc03fffff flowid ${Web} # HTTP rule with different destination 254 | ${tc} filter add dev eth0 protocol all prio 22 u32 match mark 0x40130000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination 255 | ${tc} filter add dev eth0 protocol all prio 23 u32 match mark 0x40140000 0xc03f0000 flowid ${Web} #recreate HTTPS rule with different destination 256 | ##UPLOAD APP_DB TRAFFIC REDIRECTION RULES START HERE -- legacy method 257 | 258 | ${tc} filter add dev eth0 protocol all prio 2 u32 match mark 0x4000006B 0xc03fffff flowid ${Others} #Snapchat 259 | ${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D0007 0xc03fffff flowid ${Downloads} #Speedtest.net 260 | ${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D0086 0xc03fffff flowid ${Downloads} #Google Play 261 | ${tc} filter add dev eth0 protocol all prio 15 u32 match mark 0x400D00A0 0xc03fffff flowid ${Downloads} #Apple AppStore 262 | ${tc} filter add dev eth0 protocol all prio 50 u32 match mark 0x401A0000 0xc03f0000 flowid ${Downloads} #Advertisement 263 | 264 | ##UPLOAD APP_DB TRAFFIC REDIRECTION RULES END HERE -- legacy method 265 | ${tc} filter add dev eth0 protocol all prio $1 u32 match mark 0x40000000 0x4000ffff flowid ${Others} #recreate unidentified traffic rule with different destination - Routes Unidentified Traffic into webUI adjustable "Others" traffic container, instead of "Default" traffic container 266 | ${tc} filter add dev eth0 protocol all prio 10 u32 match mark 0x403f0001 0xc03fffff flowid ${Defaults} #Used for iptables Default_mark_up functionality 267 | } 268 | 269 | custom_rates() { 270 | echo "Modifying TC Class Rates" 271 | ${tc} class change dev br0 parent 1:1 classid 1:10 htb ${PARMS}prio 0 rate ${DownRate0}Kbit ceil ${DownCeil0}Kbit burst ${DownBurst0} cburst ${DownCburst0} 272 | ${tc} class change dev br0 parent 1:1 classid 1:11 htb ${PARMS}prio 1 rate ${DownRate1}Kbit ceil ${DownCeil1}Kbit burst ${DownBurst1} cburst ${DownCburst1} 273 | ${tc} class change dev br0 parent 1:1 classid 1:12 htb ${PARMS}prio 2 rate ${DownRate2}Kbit ceil ${DownCeil2}Kbit burst ${DownBurst2} cburst ${DownCburst2} 274 | ${tc} class change dev br0 parent 1:1 classid 1:13 htb ${PARMS}prio 3 rate ${DownRate3}Kbit ceil ${DownCeil3}Kbit burst ${DownBurst3} cburst ${DownCburst3} 275 | ${tc} class change dev br0 parent 1:1 classid 1:14 htb ${PARMS}prio 4 rate ${DownRate4}Kbit ceil ${DownCeil4}Kbit burst ${DownBurst4} cburst ${DownCburst4} 276 | ${tc} class change dev br0 parent 1:1 classid 1:15 htb ${PARMS}prio 5 rate ${DownRate5}Kbit ceil ${DownCeil5}Kbit burst ${DownBurst5} cburst ${DownCburst5} 277 | ${tc} class change dev br0 parent 1:1 classid 1:16 htb ${PARMS}prio 7 rate ${DownRate6}Kbit ceil ${DownCeil6}Kbit burst ${DownBurst6} cburst ${DownCburst6} 278 | ${tc} class change dev br0 parent 1:1 classid 1:17 htb ${PARMS}prio 6 rate ${DownRate7}Kbit ceil ${DownCeil7}Kbit burst ${DownBurst7} cburst ${DownCburst7} 279 | 280 | ${tc} class change dev eth0 parent 1:1 classid 1:10 htb ${PARMS}prio 0 rate ${UpRate0}Kbit ceil ${UpCeil0}Kbit burst ${UpBurst0} cburst ${UpCburst0} 281 | ${tc} class change dev eth0 parent 1:1 classid 1:11 htb ${PARMS}prio 1 rate ${UpRate1}Kbit ceil ${UpCeil1}Kbit burst ${UpBurst1} cburst ${UpCburst1} 282 | ${tc} class change dev eth0 parent 1:1 classid 1:12 htb ${PARMS}prio 2 rate ${UpRate2}Kbit ceil ${UpCeil2}Kbit burst ${UpBurst2} cburst ${UpCburst2} 283 | ${tc} class change dev eth0 parent 1:1 classid 1:13 htb ${PARMS}prio 3 rate ${UpRate3}Kbit ceil ${UpCeil3}Kbit burst ${UpBurst3} cburst ${UpCburst3} 284 | ${tc} class change dev eth0 parent 1:1 classid 1:14 htb ${PARMS}prio 4 rate ${UpRate4}Kbit ceil ${UpCeil4}Kbit burst ${UpBurst4} cburst ${UpCburst4} 285 | ${tc} class change dev eth0 parent 1:1 classid 1:15 htb ${PARMS}prio 5 rate ${UpRate5}Kbit ceil ${UpCeil5}Kbit burst ${UpBurst5} cburst ${UpCburst5} 286 | ${tc} class change dev eth0 parent 1:1 classid 1:16 htb ${PARMS}prio 7 rate ${UpRate6}Kbit ceil ${UpCeil6}Kbit burst ${UpBurst6} cburst ${UpCburst6} 287 | ${tc} class change dev eth0 parent 1:1 classid 1:17 htb ${PARMS}prio 6 rate ${UpRate7}Kbit ceil ${UpCeil7}Kbit burst ${UpBurst7} cburst ${UpCburst7} 288 | } 289 | 290 | #################### DO NOT MODIFY BELOW ##################### 291 | #################### DO NOT MODIFY BELOW ##################### 292 | #################### DO NOT MODIFY BELOW ##################### 293 | #################### DO NOT MODIFY BELOW ##################### 294 | #################### DO NOT MODIFY BELOW ##################### 295 | #################### DO NOT MODIFY BELOW ##################### 296 | #################### DO NOT MODIFY BELOW ##################### 297 | #################### DO NOT MODIFY BELOW ##################### 298 | #################### DO NOT MODIFY BELOW ##################### 299 | #################### DO NOT MODIFY BELOW ##################### 300 | #################### DO NOT MODIFY BELOW ##################### 301 | 302 | webpath='/jffs/scripts/www_FreshJR_QoS_Stats.asp' #path of FreshJR_QoS_Stats.asp 303 | 304 | #marks for iptable rules 305 | Net_mark_down="0x80090001" 306 | VOIP_mark_down="0x80060001" # Marks for iptables variant of download rules 307 | Gaming_mark_down="0x80080001" # Note these marks are same as filter match/mask combo but have a 1 at the end. That trailing 1 prevents them from being caught by unidentified mask 308 | Others_mark_down="0x800a0001" 309 | Web_mark_down="0x800d0001" 310 | Streaming_mark_down="0x80040001" 311 | Downloads_mark_down="0x80030001" 312 | Default_mark_down="0x803f0001" 313 | 314 | Net_mark_up="0x40090001" 315 | VOIP_mark_up="0x40060001" # Marks for iptables variant of upload rules 316 | Gaming_mark_up="0x40080001" # Note these marks are same as filter match/mask combo but have a 1 at the end. That trailing 1 prevents them from being caught by unidentified mask 317 | Others_mark_up="0x400a0001" 318 | Web_mark_up="0x400d0001" 319 | Streaming_mark_up="0x40040001" 320 | Downloads_mark_up="0x40030001" 321 | Default_mark_up="0x403f0001" 322 | 323 | set_tc_variables(){ 324 | 325 | if [ -e "/usr/sbin/realtc" ] ; then 326 | tc="realtc" 327 | else 328 | tc="tc" 329 | fi 330 | 331 | #read order of QOS categories 332 | Defaults="1:17" 333 | Net="1:10" 334 | flowid=0 335 | while read -r line; # reads users order of QOS categories 336 | do 337 | #logger -s "${line} ${flowid}" 338 | case ${line} in 339 | '0') 340 | VOIP="1:1${flowid}" 341 | eval "Cat${flowid}DownBandPercent=${drp1}" 342 | eval "Cat${flowid}UpBandPercent=${urp1}" 343 | eval "Cat${flowid}DownCeilPercent=${dcp1}" 344 | eval "Cat${flowid}UpCeilPercent=${ucp1}" 345 | ;; 346 | '1') 347 | Downloads="1:1${flowid}" 348 | eval "Cat${flowid}DownBandPercent=${drp7}" 349 | eval "Cat${flowid}UpBandPercent=${urp7}" 350 | eval "Cat${flowid}DownCeilPercent=${dcp7}" 351 | eval "Cat${flowid}UpCeilPercent=${ucp7}" 352 | ;; 353 | '4') 354 | Streaming="1:1${flowid}" 355 | eval "Cat${flowid}DownBandPercent=${drp5}" 356 | eval "Cat${flowid}UpBandPercent=${urp5}" 357 | eval "Cat${flowid}DownCeilPercent=${dcp5}" 358 | eval "Cat${flowid}UpCeilPercent=${ucp5}" 359 | ;; 360 | '7') 361 | Others="1:1${flowid}" 362 | eval "Cat${flowid}DownBandPercent=${drp3}" 363 | eval "Cat${flowid}UpBandPercent=${urp3}" 364 | eval "Cat${flowid}DownCeilPercent=${dcp3}" 365 | eval "Cat${flowid}UpCeilPercent=${ucp3}" 366 | ;; 367 | '8') 368 | Gaming="1:1${flowid}" 369 | eval "Cat${flowid}DownBandPercent=${drp2}" 370 | eval "Cat${flowid}UpBandPercent=${urp2}" 371 | eval "Cat${flowid}DownCeilPercent=${dcp2}" 372 | eval "Cat${flowid}UpCeilPercent=${ucp2}" 373 | ;; 374 | '9') 375 | #net control 376 | flowid=0 377 | ;; 378 | '13') 379 | Web="1:1${flowid}" 380 | eval "Cat${flowid}DownBandPercent=${drp4}" 381 | eval "Cat${flowid}UpBandPercent=${urp4}" 382 | eval "Cat${flowid}DownCeilPercent=${dcp4}" 383 | eval "Cat${flowid}UpCeilPercent=${ucp4}" 384 | ;; 385 | esac 386 | 387 | firstchar="${line%%[0-9]*}" 388 | if [ "${firstchar}" == "[" ] ; then 389 | flowid=$((flowid + 1)) 390 | #logger -s "flowid = ${flowid} ===========" 391 | fi 392 | 393 | done </;/g' | tr -cd ';' | wc -c) -ne 20 ] ; then 729 | $(nvram set fb_comment=";;;;;;>;;;;;;>;;;;;;") 730 | fi 731 | 732 | if [ $(nvram get fb_email_dbg | sed 's/>/;/g' | tr -cd ';' | wc -c) -ne 48 ] ; then 733 | $(nvram set fb_email_dbg=";;;;;;>;>;>;>;>>>5;20;15;10;10;30;5;5>100;100;100;100;100;100;100;100>5;20;15;30;10;10;5;5>100;100;100;100;100;100;100;100") 734 | fi 735 | 736 | read \ 737 | e1 e2 e3 e4 e5 e6 e7 \ 738 | f1 f2 f3 f4 f5 f6 f7 \ 739 | g1 g2 g3 g4 g5 g6 g7 \ 740 | </;/g' ) 742 | EOF 743 | 744 | read \ 745 | h1 h2 h3 h4 h5 h6 h7 \ 746 | r1 d1 \ 747 | r2 d2 \ 748 | r3 d3 \ 749 | r4 d4 \ 750 | gameCIDR \ 751 | ruleFLAG \ 752 | drp0 drp1 drp2 drp3 drp4 drp5 drp6 drp7 \ 753 | dcp0 dcp1 dcp2 dcp3 dcp4 dcp5 dcp6 dcp7 \ 754 | urp0 urp1 urp2 urp3 urp4 urp5 urp6 urp7 \ 755 | ucp0 ucp1 ucp2 ucp3 ucp4 ucp5 ucp6 ucp7 \ 756 | </;/g' ) 758 | EOF 759 | IFS=$OLDIFS 760 | 761 | #Verify each read nvram rate is between 5-100 (disabled unless needed in future) 762 | # [ "${drp0//[^0-9]}" -ge "5" ] && [ "${drp0//[^0-9]}" -le "100" ] && drp0="5" 763 | # [ "${drp1//[^0-9]}" -ge "5" ] && [ "${drp1//[^0-9]}" -le "100" ] && drp1="20" 764 | # [ "${drp2//[^0-9]}" -ge "5" ] && [ "${drp2//[^0-9]}" -le "100" ] && drp2="15" 765 | # [ "${drp3//[^0-9]}" -ge "5" ] && [ "${drp3//[^0-9]}" -le "100" ] && drp3="10" 766 | # [ "${drp4//[^0-9]}" -ge "5" ] && [ "${drp4//[^0-9]}" -le "100" ] && drp4="10" 767 | # [ "${drp5//[^0-9]}" -ge "5" ] && [ "${drp5//[^0-9]}" -le "100" ] && drp5="30" 768 | # [ "${drp6//[^0-9]}" -ge "5" ] && [ "${drp6//[^0-9]}" -le "100" ] && drp6="5" 769 | # [ "${drp7//[^0-9]}" -ge "5" ] && [ "${drp7//[^0-9]}" -le "100" ] && drp7="5" 770 | 771 | # [ "${dcp0//[^0-9]}" -ge "5" ] && [ "${dcp0//[^0-9]}" -le "100" ] && dcp0="100" 772 | # [ "${dcp1//[^0-9]}" -ge "5" ] && [ "${dcp1//[^0-9]}" -le "100" ] && dcp1="100" 773 | # [ "${dcp2//[^0-9]}" -ge "5" ] && [ "${dcp2//[^0-9]}" -le "100" ] && dcp2="100" 774 | # [ "${dcp3//[^0-9]}" -ge "5" ] && [ "${dcp3//[^0-9]}" -le "100" ] && dcp3="100" 775 | # [ "${dcp4//[^0-9]}" -ge "5" ] && [ "${dcp4//[^0-9]}" -le "100" ] && dcp4="100" 776 | # [ "${dcp5//[^0-9]}" -ge "5" ] && [ "${dcp5//[^0-9]}" -le "100" ] && dcp5="100" 777 | # [ "${dcp6//[^0-9]}" -ge "5" ] && [ "${dcp6//[^0-9]}" -le "100" ] && dcp6="100" 778 | # [ "${dcp7//[^0-9]}" -ge "5" ] && [ "${dcp7//[^0-9]}" -le "100" ] && dcp7="100" 779 | 780 | # [ "${urp0//[^0-9]}" -ge "5" ] && [ "${urp0//[^0-9]}" -le "100" ] && urp0="5" 781 | # [ "${urp1//[^0-9]}" -ge "5" ] && [ "${urp1//[^0-9]}" -le "100" ] && urp1="20" 782 | # [ "${urp2//[^0-9]}" -ge "5" ] && [ "${urp2//[^0-9]}" -le "100" ] && urp2="15" 783 | # [ "${urp3//[^0-9]}" -ge "5" ] && [ "${urp3//[^0-9]}" -le "100" ] && urp3="30" 784 | # [ "${urp4//[^0-9]}" -ge "5" ] && [ "${urp4//[^0-9]}" -le "100" ] && urp4="10" 785 | # [ "${urp5//[^0-9]}" -ge "5" ] && [ "${urp5//[^0-9]}" -le "100" ] && urp5="10" 786 | # [ "${urp6//[^0-9]}" -ge "5" ] && [ "${urp6//[^0-9]}" -le "100" ] && urp6="5" 787 | # [ "${urp7//[^0-9]}" -ge "5" ] && [ "${urp7//[^0-9]}" -le "100" ] && urp7="5" 788 | 789 | # [ "${ucp0//[^0-9]}" -ge "5" ] && [ "${ucp0//[^0-9]}" -le "100" ] && ucp0="100" 790 | # [ "${ucp1//[^0-9]}" -ge "5" ] && [ "${ucp1//[^0-9]}" -le "100" ] && ucp1="100" 791 | # [ "${ucp2//[^0-9]}" -ge "5" ] && [ "${ucp2//[^0-9]}" -le "100" ] && ucp2="100" 792 | # [ "${ucp3//[^0-9]}" -ge "5" ] && [ "${ucp3//[^0-9]}" -le "100" ] && ucp3="100" 793 | # [ "${ucp4//[^0-9]}" -ge "5" ] && [ "${ucp4//[^0-9]}" -le "100" ] && ucp4="100" 794 | # [ "${ucp5//[^0-9]}" -ge "5" ] && [ "${ucp5//[^0-9]}" -le "100" ] && ucp5="100" 795 | # [ "${ucp6//[^0-9]}" -ge "5" ] && [ "${ucp6//[^0-9]}" -le "100" ] && ucp6="100" 796 | # [ "${ucp7//[^0-9]}" -ge "5" ] && [ "${ucp7//[^0-9]}" -le "100" ] && ucp7="100" 797 | 798 | #takes protocol saved in nvram and makes it lower case 799 | e3=$(echo ${e3} | tr '[A-Z]' '[a-z]') 800 | f3=$(echo ${f3} | tr '[A-Z]' '[a-z]') 801 | g3=$(echo ${g3} | tr '[A-Z]' '[a-z]') 802 | h3=$(echo ${h3} | tr '[A-Z]' '[a-z]') 803 | } 804 | 805 | ## helper function to save nvram variables in csv format 806 | save_nvram(){ 807 | $(nvram set fb_comment="${e1};${e2};${e3};${e4};${e5};${e6};${e7}>${f1};${f2};${f3};${f4};${f5};${f6};${f7}>${g1};${g2};${g3};${g4};${g5};${g6};${g7}") 808 | $(nvram set fb_email_dbg="${h1};${h2};${h3};${h4};${h5};${h6};${h7}>${r1};${d1}>${r2};${d2}>${r3};${d3}>${r4};${d4}>${gameCIDR}>${ruleFLAG}>${drp0};${drp1};${drp2};${drp3};${drp4};${drp5};${drp6};${drp7}>${dcp0};${dcp1};${dcp2};${dcp3};${dcp4};${dcp5};${dcp6};${dcp7}>${urp0};${urp1};${urp2};${urp3};${urp4};${urp5};${urp6};${urp7}>${ucp0};${ucp1};${ucp2};${ucp3};${ucp4};${ucp5};${ucp6};${ucp7}") 809 | $(nvram commit) 810 | } 811 | 812 | ## helper function for interactive menu mode 813 | dst_2_name() 814 | { 815 | case "$1" in 816 | 0) echo "Net Control" ;; 817 | 1) echo "Gaming" ;; 818 | 2) echo "Streaming" ;; 819 | 3) echo "VoIP" ;; 820 | 4) echo "Web Surfing" ;; 821 | 5) echo "Downloads" ;; 822 | 6) echo "Others" ;; 823 | 7) echo "Game Downloads" ;; 824 | *) echo "" ;; 825 | esac 826 | } 827 | 828 | ## helper function for interactive menu mode 829 | mark_2_name() 830 | { 831 | return #function disabled since grep is kinda slow 832 | [ -z "$1" ] && return 833 | cat="$( echo ${1} | head -c2 )" 834 | id="$( echo ${1} | tail -c -5 )" 835 | cat="$(printf "%d" 0x${cat})" 836 | id="$(printf "%d" 0x${id})" 837 | cat /tmp/bwdpi/bwdpi.app.db | grep "^${cat},${id}" | head -n1 | cut -d',' -f4 838 | } 839 | 840 | ## INTERACTIVE mode - rate main page (overview) 841 | rates(){ 842 | echo -en "\033c\e[3J" #clear screen 843 | echo -en '\033[?7l' #disable line wrap 844 | printf '\e[8;30;120t' #set height/width of terminal 845 | echo -e "\033[1;32mFreshJR QOS v${version}\033[0m" 846 | echo "QoS Rates: -------Download------- --------Upload--------" 847 | echo " Minimum Maximum Minimum Maximum" 848 | echo " Reserved Reserved Allowed Allowed" 849 | echo " Bandwidth Bandwidth Bandwidth Bandwidth" 850 | echo " (%) (%) (%) (%) " 851 | echo " ----------------------- -----------------------" 852 | format="%-15s %-13s %-18s %-13s %-4s\n" 853 | printf "${format}" "Net Control" "${drp0}" "${dcp0}" "${urp0}" "${ucp0}" 854 | printf "${format}" "VoIP" "${drp1}" "${dcp1}" "${urp1}" "${ucp1}" 855 | printf "${format}" "Gaming" "${drp2}" "${dcp2}" "${urp2}" "${ucp2}" 856 | printf "${format}" "Others" "${drp3}" "${dcp3}" "${urp3}" "${ucp3}" 857 | printf "${format}" "Web Surfing" "${drp4}" "${dcp4}" "${urp4}" "${ucp4}" 858 | printf "${format}" "Streaming" "${drp5}" "${dcp5}" "${urp5}" "${ucp5}" 859 | printf "${format}" "Game Downloads" "${drp6}" "${dcp6}" "${urp6}" "${ucp6}" 860 | printf "${format}" "File Downloads" "${drp7}" "${dcp7}" "${urp7}" "${ucp7}" 861 | echo "" 862 | echo "Available actions:" 863 | echo "" 864 | echo "1) Minimum Reserved Bandwidth -- Download" 865 | echo "2) Minimum Reserved Bandwidth -- Upload" 866 | echo "" 867 | echo "3) Maximum Allowed Bandwidth -- Download" 868 | echo "4) Maximum Allowed Bandwidth -- Upload" 869 | echo "" 870 | echo "r) Reset Values to Defaults" 871 | echo "s) Save & Exit" 872 | echo "e) Exit" 873 | echo -en '\033[?7h' #enable line wrap 874 | echo "" 875 | echo -n "What would you like to do (Enter 1-10): " 876 | read input 877 | echo -en "\033[1A\r\033[0K" 878 | echo -en "\033[1A\r\033[0K" 879 | echo -en "\033[1A\r\033[0K" 880 | echo -en "\033[1A\r\033[0K" 881 | echo -en "\033[1A\r\033[0K" 882 | echo -en "\033[1A\r\033[0K" 883 | echo -en "\033[1A\r\033[0K" 884 | echo -en "\033[1A\r\033[0K" 885 | echo -en "\033[1A\r\033[0K" 886 | echo -en "\033[1A\r\033[0K" 887 | echo -en "\033[1A\r\033[0K" 888 | case $input in 889 | 1) 890 | echo "Minimum Reserved Bandwidth" 891 | read -p " Net Control : " in0 892 | read -p " Voip : " in1 893 | read -p " Gaming : " in2 894 | read -p " Others : " in3 895 | read -p " Web Surfing : " in4 896 | read -p " Streaming : " in5 897 | read -p " Game Downloads : " in6 898 | read -p " File Downloads : " in7 899 | [ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && drp0="${in0//[^0-9]}" 900 | [ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && drp1="${in1//[^0-9]}" 901 | [ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && drp2="${in2//[^0-9]}" 902 | [ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && drp3="${in3//[^0-9]}" 903 | [ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && drp4="${in4//[^0-9]}" 904 | [ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && drp5="${in5//[^0-9]}" 905 | [ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && drp6="${in6//[^0-9]}" 906 | [ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && drp7="${in7//[^0-9]}" 907 | rates 908 | ;; 909 | 2) 910 | echo "Minimum Reserved Bandwidth" 911 | read -p " Net Control : " in0 912 | read -p " Voip : " in1 913 | read -p " Gaming : " in2 914 | read -p " Others : " in3 915 | read -p " Web Surfing : " in4 916 | read -p " Streaming : " in5 917 | read -p " Game Downloads : " in6 918 | read -p " File Downloads : " in7 919 | [ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && urp0="${in0//[^0-9]}" 920 | [ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && urp1="${in1//[^0-9]}" 921 | [ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && urp2="${in2//[^0-9]}" 922 | [ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && urp3="${in3//[^0-9]}" 923 | [ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && urp4="${in4//[^0-9]}" 924 | [ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && urp5="${in5//[^0-9]}" 925 | [ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && urp6="${in6//[^0-9]}" 926 | [ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && urp7="${in7//[^0-9]}" 927 | rates 928 | ;; 929 | 3) 930 | echo "Minimum Reserved Bandwidth" 931 | read -p " Net Control : " in0 932 | read -p " Voip : " in1 933 | read -p " Gaming : " in2 934 | read -p " Others : " in3 935 | read -p " Web Surfing : " in4 936 | read -p " Streaming : " in5 937 | read -p " Game Downloads : " in6 938 | read -p " File Downloads : " in7 939 | [ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && dcp0="${in0//[^0-9]}" 940 | [ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && dcp1="${in1//[^0-9]}" 941 | [ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && dcp2="${in2//[^0-9]}" 942 | [ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && dcp3="${in3//[^0-9]}" 943 | [ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && dcp4="${in4//[^0-9]}" 944 | [ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && dcp5="${in5//[^0-9]}" 945 | [ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && dcp6="${in6//[^0-9]}" 946 | [ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && dcp7="${in7//[^0-9]}" 947 | rates 948 | ;; 949 | 4) 950 | echo "Minimum Reserved Bandwidth" 951 | read -p " Net Control : " in0 952 | read -p " Voip : " in1 953 | read -p " Gaming : " in2 954 | read -p " Others : " in3 955 | read -p " Web Surfing : " in4 956 | read -p " Streaming : " in5 957 | read -p " Game Downloads : " in6 958 | read -p " File Downloads : " in7 959 | [ "${in0//[^0-9]}" -ge "5" ] && [ "${in0//[^0-9]}" -le "100" ] && ucp0="${in0//[^0-9]}" 960 | [ "${in1//[^0-9]}" -ge "5" ] && [ "${in1//[^0-9]}" -le "100" ] && ucp1="${in1//[^0-9]}" 961 | [ "${in2//[^0-9]}" -ge "5" ] && [ "${in2//[^0-9]}" -le "100" ] && ucp2="${in2//[^0-9]}" 962 | [ "${in3//[^0-9]}" -ge "5" ] && [ "${in3//[^0-9]}" -le "100" ] && ucp3="${in3//[^0-9]}" 963 | [ "${in4//[^0-9]}" -ge "5" ] && [ "${in4//[^0-9]}" -le "100" ] && ucp4="${in4//[^0-9]}" 964 | [ "${in5//[^0-9]}" -ge "5" ] && [ "${in5//[^0-9]}" -le "100" ] && ucp5="${in5//[^0-9]}" 965 | [ "${in6//[^0-9]}" -ge "5" ] && [ "${in6//[^0-9]}" -le "100" ] && ucp6="${in6//[^0-9]}" 966 | [ "${in7//[^0-9]}" -ge "5" ] && [ "${in7//[^0-9]}" -le "100" ] && ucp7="${in7//[^0-9]}" 967 | rates 968 | ;; 969 | 'r'|'R') 970 | drp0="5" 971 | drp1="20" 972 | drp2="15" 973 | drp3="10" 974 | drp4="10" 975 | drp5="30" 976 | drp6="5" 977 | drp7="5" 978 | 979 | dcp0="100" 980 | dcp1="100" 981 | dcp2="100" 982 | dcp3="100" 983 | dcp4="100" 984 | dcp5="100" 985 | dcp6="100" 986 | dcp7="100" 987 | 988 | urp0="5" 989 | urp1="20" 990 | urp2="15" 991 | urp3="30" 992 | urp4="10" 993 | urp5="10" 994 | urp6="5" 995 | urp7="5" 996 | 997 | ucp0="100" 998 | ucp1="100" 999 | ucp2="100" 1000 | ucp3="100" 1001 | ucp4="100" 1002 | ucp5="100" 1003 | ucp6="100" 1004 | ucp7="100" 1005 | rates 1006 | ;; 1007 | 's'|'S') 1008 | save_nvram 1009 | echo " Saving Changes" 1010 | [ "$(nvram get qos_enable)" == "1" ] && prompt_restart 1011 | return 1 1012 | ;; 1013 | 'e'|'E') 1014 | echo -e "\033[1;31;7m No Changes have been saved \033[0m" 1015 | echo "" 1016 | return 0 ;; 1017 | *) 1018 | rates ;; 1019 | esac 1020 | } 1021 | 1022 | ## INTERACTIVE mode - rule main page (overview) 1023 | rules(){ 1024 | echo -en "\033c\e[3J" #clear screen 1025 | echo -en '\033[?7l' #disable line wrap 1026 | printf '\e[8;30;120t' #set height/width of terminal 1027 | echo -e "\033[1;32mFreshJR QOS v${version}\033[0m" 1028 | echo "Custom QoS Rules:" 1029 | echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst" 1030 | printf '1) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")" 1031 | printf '2) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")" 1032 | printf '3) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")" 1033 | printf '4) Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")" 1034 | printf '5) Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming" 1035 | printf '6) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")" 1036 | printf '7) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")" 1037 | printf '8) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")" 1038 | printf '9) Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")" 1039 | 1040 | echo "" 1041 | echo "s) Save & Exit" 1042 | echo "e) Exit" 1043 | echo -en '\033[?7h' #enable line wrap 1044 | echo "" 1045 | echo -n "Select Rule to Modify (Enter 1-9): " 1046 | read input 1047 | case $input in 1048 | '1') iprule e1 e2 e3 e4 e5 e6 e7 "Rule 1";; 1049 | '2') iprule f1 f2 f3 f4 f5 f6 f7 "Rule 2";; 1050 | '3') iprule g1 g2 g3 g4 g5 g6 g7 "Rule 3";; 1051 | '4') iprule h1 h2 h3 h4 h5 h6 h7 "Rule 4";; 1052 | '5') gamerule ;; 1053 | '6') apprule r1 d1 "Appdb 1" ;; 1054 | '7') apprule r2 d2 "Appdb 2" ;; 1055 | '8') apprule r3 d3 "Appdb 3" ;; 1056 | '9') apprule r4 d4 "Appdb 4" ;; 1057 | 's'|'S') 1058 | echo "" 1059 | echo "Saving Changes" 1060 | save_nvram 1061 | [ "$(nvram get qos_enable)" == "1" ] && prompt_restart 1062 | return 1 1063 | ;; 1064 | 'e'|'E') 1065 | echo "" 1066 | echo -e "\033[1;31;7m No Changes have been saved \033[0m" 1067 | echo "" 1068 | return 0 ;; 1069 | *) 1070 | rules ;; 1071 | esac 1072 | } 1073 | 1074 | ## INTERACTIVE mode - modify iptable rule 1075 | iprule() 1076 | { 1077 | echo -en "\033c\e[3J" 1078 | echo -en '\033[?7l' #disable line wrap 1079 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 1080 | echo "Modifying ${8}" 1081 | echo -n "1) Name " && sed -nE 's/var rulename'${8//[^0-9]/}'="(.*?)";/\1/p' "${webpath}" 1082 | echo -n "2) Local IP " && eval "echo \${$1}" 1083 | echo -n "3) Remote IP " && eval "echo \${$2}" 1084 | echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate 1085 | echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate 1086 | echo -n "6) Protocol " && eval "echo \${$3}" 1087 | echo -n "7) QoS Mark " && eval "echo \${$6}" 1088 | echo -n "8) Destination " && eval "dst_2_name \${$7}" 1089 | echo "" 1090 | echo "r) Reset / Disable" 1091 | echo "e) Go Back" 1092 | echo "" 1093 | in_progress=1 1094 | while [ ${in_progress} -eq 1 ] ; do 1095 | echo -n "Select Parameter to Modify (Enter 1-8): " 1096 | read input 1097 | echo -en "\033[1A\r\033[0K" #clear user input prompt 1098 | case $input in 1099 | 1) #name 1100 | echo -ne "\033[1;32m" 1101 | echo " WebUI Rule Name" 1102 | echo "" 1103 | echo -ne "\033[0m" 1104 | echo -n " Name(Rule${8//[^0-9]/})=" 1105 | #read user input 1106 | read input 1107 | if [ -z $input ] ; then 1108 | input="${8// /}" 1109 | fi 1110 | echo -en "\033[1A\r\033[0K" 1111 | echo -en "\033[1A\r\033[0K" 1112 | echo -en "\033[1A\r\033[0K" 1113 | #make changes to WebUI.asp page 1114 | echo "$( cat "${webpath}" | sed -E 's/var rulename'"${8//[^0-9]/}"'="(.*?)";/var rulename'"${8//[^0-9]/}"'="'"${input}"'";/')" > "${webpath}" 1115 | #update table entry 1116 | echo -en "\033[3;0f\033[0K" #move to line 3 pos 0 \ erase to end 1117 | echo -n "1) Name " && sed -nE 's/var rulename'${8//[^0-9]/}'="(.*?)";/\1/p' "${webpath}" 1118 | ;; 1119 | 1120 | 2) #local ip 1121 | #show valid syntax 1122 | echo -ne "\033[1;32m" 1123 | echo " Local IP Syntax: 192.168.X.XXX or !192.168.X.XXX" 1124 | echo " 192.168.X.XXX/CIDR or !192.168.X.XXX/CIDR" 1125 | echo "" 1126 | echo -ne "\033[0m" 1127 | echo -n " Local IP=" 1128 | #read user input 1129 | read input 1130 | eval "$1=\$input" 1131 | #clear syntax+input 1132 | echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end 1133 | echo -en "\033[1A\r\033[0K" 1134 | echo -en "\033[1A\r\033[0K" 1135 | echo -en "\033[1A\r\033[0K" 1136 | #update table entry 1137 | echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end 1138 | echo -n "2) Local IP " && eval "echo \${$1}" 1139 | ;; 1140 | 3) #remote ip 1141 | #show valid syntax 1142 | echo -ne "\033[1;32m" 1143 | echo " Remote IP Syntax: 75.75.75.75 or !75.75.75.75 " 1144 | echo " 75.75.75.75/CIDR or !75.75.75.75/CIDR" 1145 | echo "" 1146 | echo -ne "\033[0m" 1147 | echo -n " Remote IP=" 1148 | #read user input 1149 | read input 1150 | eval "$2=\$input" 1151 | #clear syntax+input 1152 | echo -en "\033[1A\r\033[0K" 1153 | echo -en "\033[1A\r\033[0K" 1154 | echo -en "\033[1A\r\033[0K" 1155 | echo -en "\033[1A\r\033[0K" 1156 | #update table entry 1157 | echo -en "\033[5;0f\033[0K" #move to line 5 pos 0 \ erase to end 1158 | echo -n "3) Remote IP " && eval "echo \${$2}" 1159 | ;; 1160 | 4) #local port 1161 | #show valid syntax 1162 | echo -ne "\033[1;32m" 1163 | echo " Local Port Syntax: XXX or !XXX" 1164 | echo " XXXX:YYYY or !XXXX:YYYY" 1165 | echo " XXX,YYY,ZZZ or !XXX,YYY,ZZZ" 1166 | echo "" 1167 | echo -ne "\033[0m" 1168 | echo -n " Local Port=" 1169 | #read user input 1170 | read input 1171 | eval "$4=\$input" 1172 | if [ -z $input ] ; then 1173 | #if port entry blank --> do not continue 1174 | #clear syntax + input 1175 | echo -en "\033[1A\r\033[0K" 1176 | echo -en "\033[1A\r\033[0K" 1177 | echo -en "\033[1A\r\033[0K" 1178 | echo -en "\033[1A\r\033[0K" 1179 | echo -en "\033[1A\r\033[0K" 1180 | #if both ports are blank then reset protocol variable 1181 | [ -z $(eval "echo \${$5}") ] && eval "$3='both'" 1182 | else 1183 | #else port was defined --> ask for protocol definition 1184 | #show additional valid syntax 1185 | echo -ne "\033[1;32m" 1186 | echo "" 1187 | echo " Protocol Syntax: tcp" 1188 | echo " udp" 1189 | echo " both" 1190 | echo "" 1191 | echo -ne "\033[0m" 1192 | echo -n " Protocol=" 1193 | #read user input 1194 | read user input 1195 | input=$(echo ${input} | tr '[A-Z]' '[a-z]') 1196 | if [ "${input}" = "udp" ] || [ "${input}" = "both" ] ; then 1197 | eval "$3=\$input" 1198 | else 1199 | eval "$3='tcp'" 1200 | fi 1201 | #clear syntax+input 1202 | echo -en "\033[1A\r\033[0K" 1203 | echo -en "\033[1A\r\033[0K" 1204 | echo -en "\033[1A\r\033[0K" 1205 | echo -en "\033[1A\r\033[0K" 1206 | echo -en "\033[1A\r\033[0K" 1207 | echo -en "\033[1A\r\033[0K" 1208 | echo -en "\033[1A\r\033[0K" 1209 | echo -en "\033[1A\r\033[0K" 1210 | echo -en "\033[1A\r\033[0K" 1211 | echo -en "\033[1A\r\033[0K" 1212 | echo -en "\033[1A\r\033[0K" 1213 | fi 1214 | #update table entry 1215 | echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end 1216 | echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end 1217 | echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end 1218 | echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate 1219 | echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate 1220 | echo -n "6) Protocol " && eval "echo \${$3}" 1221 | ;; 1222 | 5) #remote port 1223 | #show valid syntax 1224 | echo -ne "\033[1;32m" 1225 | echo " Remote Port Syntax: XXX or !XXX" 1226 | echo " XXXX:YYYY or !XXXX:YYYY" 1227 | echo " XXX,YYY,ZZZ or !XXX,YYY,ZZZ" 1228 | echo "" 1229 | echo -ne "\033[0m" 1230 | echo -n " Remote Port=" 1231 | #read user input 1232 | read input 1233 | eval "$5=\$input" 1234 | if [ -z $input ] ; then 1235 | #if port entry blank --> do not continue 1236 | #clear syntax + input 1237 | echo -en "\033[1A\r\033[0K" 1238 | echo -en "\033[1A\r\033[0K" 1239 | echo -en "\033[1A\r\033[0K" 1240 | echo -en "\033[1A\r\033[0K" 1241 | echo -en "\033[1A\r\033[0K" 1242 | #if both ports are blank then also clear protocol variable 1243 | [ -z $(eval "echo \${$4}") ] && eval "$3='both'" 1244 | else 1245 | #else port was defined --> ask for protocol definition 1246 | #show additional valid syntax 1247 | echo -ne "\033[1;32m" 1248 | echo "" 1249 | echo " Protocol Syntax: tcp" 1250 | echo " udp" 1251 | echo " both" 1252 | echo "" 1253 | echo -ne "\033[0m" 1254 | echo -n " Protocol=" 1255 | #read user input 1256 | read input 1257 | input=$(echo ${input} | tr '[A-Z]' '[a-z]') 1258 | if [ "${input}" = "udp" ] || [ "${input}" = "both" ] ; then 1259 | eval "$3=\$input" 1260 | else 1261 | eval "$3='tcp'" 1262 | fi 1263 | #clear syntax+input 1264 | echo -en "\033[1A\r\033[0K" 1265 | echo -en "\033[1A\r\033[0K" 1266 | echo -en "\033[1A\r\033[0K" 1267 | echo -en "\033[1A\r\033[0K" 1268 | echo -en "\033[1A\r\033[0K" 1269 | echo -en "\033[1A\r\033[0K" 1270 | echo -en "\033[1A\r\033[0K" 1271 | echo -en "\033[1A\r\033[0K" 1272 | echo -en "\033[1A\r\033[0K" 1273 | echo -en "\033[1A\r\033[0K" 1274 | echo -en "\033[1A\r\033[0K" 1275 | fi 1276 | #update table entry 1277 | echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end 1278 | echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end 1279 | echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end 1280 | echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate 1281 | echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate 1282 | echo -n "6) Protocol " && eval "echo \${$3}" 1283 | ;; 1284 | 6) #protocol 1285 | #show valid syntax 1286 | echo -ne "\033[1;32m" 1287 | echo " Protocol Syntax: tcp" 1288 | echo " udp" 1289 | echo " both" 1290 | echo "" 1291 | echo -ne "\033[0m" 1292 | echo -n " Protocol=" 1293 | #read user input 1294 | read input 1295 | input=$(echo ${input} | tr '[A-Z]' '[a-z]') 1296 | if [ "${input}" = "udp" ] || [ "${input}" = "tcp" ] ; then 1297 | eval "$3=\$input" 1298 | else 1299 | eval "$3='both'" 1300 | fi 1301 | #clear sytnax + input 1302 | echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end 1303 | echo -en "\033[1A\r\033[0K" 1304 | echo -en "\033[1A\r\033[0K" 1305 | echo -en "\033[1A\r\033[0K" 1306 | echo -en "\033[1A\r\033[0K" 1307 | #update table entry 1308 | echo -en "\033[8;0f\033[0K" #move to line 8 pos 0 \ erase to end 1309 | echo -en "\033[7;0f\033[0K" #move to line 7 pos 0 \ erase to end 1310 | echo -en "\033[6;0f\033[0K" #move to line 6 pos 0 \ erase to end 1311 | echo -n "4) Local Port " && [ -z $(eval "echo \${$4}") ] && echo || eval "echo \${$3} \${$4}" #if ${4} is blank then leave field blank else populate 1312 | echo -n "5) Remote Port " && [ -z $(eval "echo \${$5}") ] && echo || eval "echo \${$3} \${$5}" #if ${5} is blank then leave field blank else populate 1313 | echo -n "6) Protocol " && eval "echo \${$3}" 1314 | ;; 1315 | 7) #qos mark 1316 | #show valid syntax 1317 | echo -ne "\033[1;32m" 1318 | echo " QoS Mark Syntax (hex): XXYYYY" 1319 | echo " Note: YYYY can be **** wildcard" 1320 | echo "" 1321 | echo -ne "\033[0m" 1322 | echo -n " QoS Mark=" 1323 | #read user input 1324 | read input 1325 | input=${input//!/} 1326 | eval "$6=\$input" 1327 | #clear sytnax + input 1328 | echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end 1329 | echo -en "\033[1A\r\033[0K" 1330 | echo -en "\033[1A\r\033[0K" 1331 | echo -en "\033[1A\r\033[0K" 1332 | #update table entry 1333 | echo -en "\033[9;0f\033[0K" #move to line 9 pos 0 \ erase to end 1334 | echo -n "7) QoS Mark " && eval "echo \${$6}" 1335 | ;; 1336 | 8) #packetdestination 1337 | #show valid syntax 1338 | echo -ne "\033[1;32m" 1339 | echo " Destination Syntax: 0-7" 1340 | echo "" 1341 | echo " Reference: " 1342 | echo " 0) Net Control" 1343 | echo " 1) VoIP" 1344 | echo " 2) Gaming" 1345 | echo " 3) Others" 1346 | echo " 4) Web Surfing" 1347 | echo " 5) Streaming" 1348 | echo " 6) Game Downloads" 1349 | echo " 7) Downloads" 1350 | echo "" 1351 | echo -ne "\033[0m" 1352 | echo -n " Destination=" 1353 | #read user input 1354 | read input 1355 | case $input in 1356 | 0) eval "$7='0'" ;; #net 1357 | 1) eval "$7='3'" ;; #voip 1358 | 2) eval "$7='1'" ;; #game 1359 | 3) eval "$7='6'" ;; #other 1360 | 4) eval "$7='4'" ;; #web 1361 | 5) eval "$7='2'" ;; #video 1362 | 6) eval "$7='7'" ;; #game download 1363 | 7) eval "$7='5'" ;; #downloads 1364 | *) eval "$7='0'" ;; #invalid input -> net 1365 | esac 1366 | #clear syntax + input 1367 | echo -en "\033[1A\r\033[0K" 1368 | echo -en "\033[1A\r\033[0K" 1369 | echo -en "\033[1A\r\033[0K" 1370 | echo -en "\033[1A\r\033[0K" 1371 | echo -en "\033[1A\r\033[0K" 1372 | echo -en "\033[1A\r\033[0K" 1373 | echo -en "\033[1A\r\033[0K" 1374 | echo -en "\033[1A\r\033[0K" 1375 | echo -en "\033[1A\r\033[0K" 1376 | echo -en "\033[1A\r\033[0K" 1377 | echo -en "\033[1A\r\033[0K" 1378 | echo -en "\033[1A\r\033[0K" 1379 | echo -en "\033[1A\r\033[0K" 1380 | #update table entry 1381 | echo -en "\033[10;0f\033[0K" #move to line 10 pos 0 \ erase to end 1382 | echo -n "8) Destination " && eval "dst_2_name \${$7}" #if all params empty leave blank else populate 1383 | ;; 1384 | 'r'|'R') #reset 1385 | eval "$1=''" 1386 | eval "$2=''" 1387 | eval "$3=''" 1388 | eval "$4=''" 1389 | eval "$5=''" 1390 | eval "$6=''" 1391 | eval "$7=''" 1392 | echo "$( cat "${webpath}" | sed -E 's/var rulename'"${8//[^0-9]/}"'="(.*?)";/var rulename'"${8//[^0-9]/}"'="Rule'"${8//[^0-9]/}"'";/')" > "${webpath}" 1393 | in_progress=0 1394 | ;; 1395 | 'e'|'E') 1396 | in_progress=0 1397 | ;; 1398 | esac 1399 | echo -en "\033[15;0f" #set cursor to user prompt original position 1400 | done 1401 | rules #go back to rules page after modifying individual rule 1402 | } 1403 | 1404 | ## INTERACTIVE mode - modify gameip range 1405 | gamerule() 1406 | { 1407 | echo -en "\033c\e[3J" 1408 | echo -en '\033[?7l' #disable line wrap 1409 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 1410 | echo "Modifying Gaming Device IP Range " 1411 | echo -ne "\033[1;32m" 1412 | echo "" 1413 | echo " Gaming Device IP Syntax: 192.168.X.XXX " 1414 | echo " 192.168.X.XXX/CIDR" 1415 | echo "" 1416 | echo -ne "\033[0m" 1417 | echo -ne " Gaming Device IP=" 1418 | read input 1419 | if [ "$( echo $input | tr -cd '.' | wc -c )" -eq "3" ] ; then 1420 | gameCIDR=${input} 1421 | else 1422 | gameCIDR='' 1423 | fi 1424 | rules 1425 | } 1426 | 1427 | ## INTERACTIVE mode - modify appdb TC rule 1428 | apprule() 1429 | { 1430 | echo -en "\033c\e[3J" 1431 | echo -en '\033[?7l' #disable line wrap 1432 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 1433 | echo "Modifying ${3}" 1434 | echo -n "1) QoS Mark " && eval "echo \${$1}" 1435 | echo -n "2) Destination " && eval "dst_2_name \${$2}" 1436 | echo "" 1437 | echo "r) Reset / Disable" 1438 | echo "e) Go Back" 1439 | echo "" 1440 | in_progress=1 1441 | while [ ${in_progress} -eq 1 ] ; do 1442 | echo -n "Select Parameter to Modify (Enter 1-2): " 1443 | read input 1444 | echo -en "\033[1A\r\033[0K" #clear user input prompt 1445 | case $input in 1446 | 1) #QoS MARK 1447 | #show valid syntax 1448 | echo -ne "\033[1;32m" 1449 | echo " QoS Mark Syntax: XXYYYY" 1450 | echo "" 1451 | echo -ne "\033[0m" 1452 | echo -n " QoS Mark=" 1453 | #read user input 1454 | read input 1455 | eval "$1=\$input" 1456 | #clear syntax + input 1457 | echo -en "\033[1A\r\033[0K" #up one line \ beginning line \ erase to end 1458 | echo -en "\033[1A\r\033[0K" 1459 | echo -en "\033[1A\r\033[0K" 1460 | #update table entry 1461 | echo -en "\033[3;0f\033[0K" #move to line 3 pos 0 \ erase to end 1462 | echo -n "1) QoS Mark " && eval "echo \${$1}" 1463 | if [ -z $(eval "echo \${$2}") ] ; then 1464 | echo -en "\033[9;0f" 1465 | #show valid syntax 1466 | echo -ne "\033[1;32m" 1467 | echo " Destination Syntax: 0-7" 1468 | echo "" 1469 | echo " Reference: " 1470 | echo " 0) Net Control" 1471 | echo " 1) VoIP" 1472 | echo " 2) Gaming" 1473 | echo " 3) Others" 1474 | echo " 4) Web Surfing" 1475 | echo " 5) Streaming" 1476 | echo " 6) Game Downloads" 1477 | echo " 7) Downloads" 1478 | echo "" 1479 | echo -ne "\033[0m" 1480 | echo -n " Destination=" 1481 | #read user input 1482 | read input 1483 | case $input in 1484 | 0) eval "$2='0'" ;; #net 1485 | 1) eval "$2='3'" ;; #voip 1486 | 2) eval "$2='1'" ;; #game 1487 | 3) eval "$2='6'" ;; #other 1488 | 4) eval "$2='4'" ;; #web 1489 | 5) eval "$2='2'" ;; #video 1490 | 6) eval "$2='7'" ;; #game download 1491 | 7) eval "$2='5'" ;; #downloads 1492 | *) eval "$2=''" ;; #invalid input -> disable 1493 | esac 1494 | #clear syntax + input 1495 | echo -en "\033[1A\r\033[0K" 1496 | echo -en "\033[1A\r\033[0K" 1497 | echo -en "\033[1A\r\033[0K" 1498 | echo -en "\033[1A\r\033[0K" 1499 | echo -en "\033[1A\r\033[0K" 1500 | echo -en "\033[1A\r\033[0K" 1501 | echo -en "\033[1A\r\033[0K" 1502 | echo -en "\033[1A\r\033[0K" 1503 | echo -en "\033[1A\r\033[0K" 1504 | echo -en "\033[1A\r\033[0K" 1505 | echo -en "\033[1A\r\033[0K" 1506 | echo -en "\033[1A\r\033[0K" 1507 | echo -en "\033[1A\r\033[0K" 1508 | #update table entry 1509 | echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end 1510 | echo -n "2) Destination " && eval "dst_2_name \${$2}" 1511 | fi 1512 | ;; 1513 | 2) #packet destination 1514 | #show valid syntax 1515 | echo -ne "\033[1;32m" 1516 | echo " Destination Syntax: 0-7" 1517 | echo "" 1518 | echo " Reference: " 1519 | echo " 0) Net Control" 1520 | echo " 1) VoIP" 1521 | echo " 2) Gaming" 1522 | echo " 3) Others" 1523 | echo " 4) Web Surfing" 1524 | echo " 5) Streaming" 1525 | echo " 6) Game Downloads" 1526 | echo " 7) Downloads" 1527 | echo "" 1528 | echo -ne "\033[0m" 1529 | echo -n " Destination=" 1530 | #read user input 1531 | read input 1532 | case $input in 1533 | 0) eval "$2='0'" ;; #net 1534 | 1) eval "$2='3'" ;; #voip 1535 | 2) eval "$2='1'" ;; #game 1536 | 3) eval "$2='6'" ;; #other 1537 | 4) eval "$2='4'" ;; #web 1538 | 5) eval "$2='2'" ;; #video 1539 | 6) eval "$2='7'" ;; #game download 1540 | 7) eval "$2='5'" ;; #downloads 1541 | *) eval "$2=''" ;; #invalid input -> disable 1542 | esac 1543 | #clear syntax + input 1544 | echo -en "\033[1A\r\033[0K" 1545 | echo -en "\033[1A\r\033[0K" 1546 | echo -en "\033[1A\r\033[0K" 1547 | echo -en "\033[1A\r\033[0K" 1548 | echo -en "\033[1A\r\033[0K" 1549 | echo -en "\033[1A\r\033[0K" 1550 | echo -en "\033[1A\r\033[0K" 1551 | echo -en "\033[1A\r\033[0K" 1552 | echo -en "\033[1A\r\033[0K" 1553 | echo -en "\033[1A\r\033[0K" 1554 | echo -en "\033[1A\r\033[0K" 1555 | echo -en "\033[1A\r\033[0K" 1556 | echo -en "\033[1A\r\033[0K" 1557 | #update table entry 1558 | echo -en "\033[4;0f\033[0K" #move to line 4 pos 0 \ erase to end 1559 | echo -n "2) Destination " && eval "dst_2_name \${$2}" 1560 | ;; 1561 | 'r'|'R') #reset 1562 | eval "$1=''" 1563 | eval "$2=''" 1564 | #apprule $1 $2 "${3}" 1565 | in_progress=0 1566 | ;; 1567 | 'e'|'E') 1568 | in_progress=0 1569 | ;; 1570 | esac 1571 | echo -en "\033[9;0f" #set cursor to user prompt original position 1572 | done 1573 | rules #go back to rules page after modifying individual rule 1574 | } 1575 | 1576 | 1577 | ## helper function - parse parameters into tc syntax 1578 | parse_tcrule() { 1579 | ##requires global variables previously set by set_tc_variables 1580 | ##----------input----------- 1581 | ##$1 = mark 1582 | ##$2 = dst 1583 | ##----------output----------- 1584 | ##byref sets $3 1585 | ##byref sets $4 1586 | 1587 | cat="$( echo ${1} | head -c2 )" 1588 | id="$( echo ${1} | tail -c -5 )" 1589 | 1590 | #filter field 1591 | if [ "$( echo ${1} | wc -c )" -eq "7" ] ; then 1592 | if [ "${id}" == "****" ] ; then 1593 | DOWN_mark="0x80${1//!/} 0xc03ff0000" 1594 | UP_mark="0x40${1//!/} 0xc03ff0000" 1595 | else 1596 | DOWN_mark="0x80${1//!/} 0xc03fffff" 1597 | UP_mark="0x40${1//!/} 0xc03fffff" 1598 | fi 1599 | else 1600 | ##return early if mark is less than 6 digits 1601 | return 1602 | fi 1603 | 1604 | #destination field 1605 | case "$2" in 1606 | 0) flowid=${Net};; 1607 | 1) flowid=${Gaming};; 1608 | 2) flowid=${Streaming};; 1609 | 3) flowid=${VOIP};; 1610 | 4) flowid=${Web};; 1611 | 5) flowid=${Downloads};; 1612 | 6) flowid=${Others};; 1613 | 7) flowid=${Defaults};; 1614 | ##return early if destination missing 1615 | *) return ;; 1616 | esac 1617 | 1618 | #prio field 1619 | prio="$(tc filter show dev br0 | grep ${cat}0000 -B1 | tail -2 | cut -d " " -f7 | head -1)" 1620 | if [ -z "${prio}" ] ; then 1621 | prio="${undf_prio}" 1622 | else 1623 | prio="$(expr ${prio} - 1)" 1624 | fi 1625 | 1626 | down_rule="prio $prio u32 match mark $DOWN_mark flowid $flowid" 1627 | up_rule="prio $prio u32 match mark $UP_mark flowid $flowid" 1628 | eval "$3=\$down_rule" 1629 | eval "$4=\$up_rule" 1630 | } 1631 | 1632 | 1633 | ## helper function - parse parameters into iptable syntax 1634 | parse_iptablerule() { 1635 | ##----------input----------- 1636 | #$1=local IP accepted XXX.XXX.XXX.XXX or !XXX.XXX.XXX.XXX 1637 | #$2=remote IP accepted XXX.XXX.XXX.XXX or !XXX.XXX.XXX.XXX 1638 | #$3=protocol accepted tcp or udp 1639 | #$4=local port accepted XXXXX or XXXXX:YYYYY or XXX,YYY,ZZZ or !XXXXX or !XXXXX:YYYYY or !XXX,YYY,ZZZ 1640 | #$5=remote port accepted XXXXX or XXXXX:YYYYY or XXX,YYY,ZZZ or !XXXXX or !XXXXX:YYYYY or !XXX,YYY,ZZZ 1641 | #$6=mark accepted XXYYYY (setting YYYY to **** will filter entire "XX" parent category) 1642 | #$7=qos destination accepted 0-7 1643 | ##----------output----------- 1644 | ##byref sets $8 1645 | ##byref sets $9 1646 | 1647 | 1648 | #local IP 1649 | if [ "$( echo ${1} | wc -c )" -gt "1" ] ; then 1650 | DOWN_Lip="${1//[^!]*/} -d ${1//!/}" 1651 | UP_Lip="${1//[^!]*/} -s ${1//!/}" 1652 | else 1653 | DOWN_Lip="" 1654 | UP_Lip="" 1655 | fi 1656 | 1657 | #remote IP 1658 | if [ "$( echo ${2} | wc -c )" -gt "1" ] ; then 1659 | DOWN_Rip="${2//[^!]*/} -s ${2//!/}" 1660 | UP_Rip="${2//[^!]*/} -d ${2//!/}" 1661 | else 1662 | DOWN_Rip="" 1663 | UP_Rip="" 1664 | fi 1665 | 1666 | #protocol (required for port rules) 1667 | if [ "${3}" = 'tcp' ] || [ "${3}" = 'udp' ] ; then #if tcp/udp 1668 | PROTO="-p ${3}" 1669 | else 1670 | if [ "$( echo ${4} | wc -c )" -gt "1" ] || [ "$( echo ${5} | wc -c )" -gt "1" ] ; then #if both & port rules defined 1671 | PROTO="-p both" #"BOTH" gets replaced with tcp & udp during later prior to rule execution 1672 | else #if both & port rules not defined 1673 | PROTO="" 1674 | fi 1675 | fi 1676 | 1677 | 1678 | #local port 1679 | if [ "$( echo ${4} | wc -c )" -gt "1" ] ; then 1680 | if [ "$( echo ${4} | tr -cd ',' | wc -c )" -ge "1" ] ; then 1681 | #multiport XXX,YYY,ZZZ 1682 | DOWN_Lport="-m multiport ${4//[^!]*/} --dports ${4//!/}" 1683 | UP_Lport="-m multiport ${4//[^!]*/} --sports ${4//!/}" 1684 | else 1685 | #single port XXX or port range XXX:YYY 1686 | DOWN_Lport="${4//[^!]*/} --dport ${4//!/}" 1687 | UP_Lport="${4//[^!]*/} --sport ${4//!/}" 1688 | fi 1689 | else 1690 | DOWN_Lport="" 1691 | UP_Lport="" 1692 | fi 1693 | 1694 | 1695 | #remote port 1696 | if [ "$( echo ${5} | wc -c )" -gt "1" ] ; then 1697 | if [ "$( echo ${5} | tr -cd ',' | wc -c )" -ge "1" ] ; then 1698 | #multiport XXX,YYY,ZZZ 1699 | DOWN_Rport="-m multiport ${5//[^!]*/} --sports ${5//!/}" 1700 | UP_Rport="-m multiport ${5//[^!]*/} --dports ${5//!/}" 1701 | else 1702 | #single port XXX or port range XXX:YYY 1703 | DOWN_Rport="${5//[^!]*/} --sport ${5//!/}" 1704 | UP_Rport="${5//[^!]*/} --dport ${5//!/}" 1705 | fi 1706 | else 1707 | DOWN_Rport="" 1708 | UP_Rport="" 1709 | fi 1710 | 1711 | #match mark 1712 | if [ "$( echo ${6} | wc -c )" -eq "7" ] ; then 1713 | if [ "$( echo ${6} | tail -c -5 )" == "****" ] ; then 1714 | DOWN_mark="-m mark --mark 0x80${6//!/}/0xc03f0000" 1715 | UP_mark="-m mark --mark 0x40${6//!/}/0xc03f0000" 1716 | else 1717 | DOWN_mark="-m mark --mark 0x80${6//!/}/0xc03fffff" 1718 | UP_mark="-m mark --mark 0x40${6//!/}/0xc03fffff" 1719 | fi 1720 | else 1721 | DOWN_mark="" 1722 | UP_mark="" 1723 | fi 1724 | 1725 | ##if parameters are empty return early 1726 | if [ -z "${DOWN_Lip}${DOWN_Rip}${DOWN_Lport}${DOWN_Rport}${DOWN_mark}" ] ; then 1727 | return 1728 | fi 1729 | 1730 | #destination mark 1731 | case "$7" in 1732 | 0) 1733 | DOWN_dst="-j MARK --set-mark ${Net_mark_down}" 1734 | UP_dst="-j MARK --set-mark ${Net_mark_up}" 1735 | ;; 1736 | 1) 1737 | DOWN_dst="-j MARK --set-mark ${Gaming_mark_down}" 1738 | UP_dst="-j MARK --set-mark ${Gaming_mark_up}" 1739 | ;; 1740 | 2) 1741 | DOWN_dst="-j MARK --set-mark ${Streaming_mark_down}" 1742 | UP_dst="-j MARK --set-mark ${Streaming_mark_up}" 1743 | ;; 1744 | 3) 1745 | DOWN_dst="-j MARK --set-mark ${VOIP_mark_down}" 1746 | UP_dst="-j MARK --set-mark ${VOIP_mark_up}" 1747 | ;; 1748 | 4) 1749 | DOWN_dst="-j MARK --set-mark ${Web_mark_down}" 1750 | UP_dst="-j MARK --set-mark ${Web_mark_up}" 1751 | ;; 1752 | 5) 1753 | DOWN_dst="-j MARK --set-mark ${Downloads_mark_down}" 1754 | UP_dst="-j MARK --set-mark ${Downloads_mark_up}" 1755 | ;; 1756 | 6) 1757 | DOWN_dst="-j MARK --set-mark ${Others_mark_down}" 1758 | UP_dst="-j MARK --set-mark ${Others_mark_up}" 1759 | ;; 1760 | 7) 1761 | DOWN_dst="-j MARK --set-mark ${Default_mark_down}" 1762 | UP_dst="-j MARK --set-mark ${Default_mark_up}" 1763 | ;; 1764 | *) 1765 | ##if destinations is empty return early 1766 | return 1767 | ;; 1768 | esac 1769 | 1770 | down_rule="$(echo "${DOWN_Lip} ${DOWN_Rip} ${PROTO} ${DOWN_Lport} ${DOWN_Rport} ${DOWN_mark} ${DOWN_dst}" | sed 's/ */ /g')" 1771 | up_rule="$(echo "${UP_Lip} ${UP_Rip} ${PROTO} ${UP_Lport} ${UP_Rport} ${UP_mark} ${UP_dst}" | sed 's/ */ /g')" 1772 | eval "$8=\$down_rule" 1773 | eval "$9=\$up_rule" 1774 | } 1775 | 1776 | about(){ 1777 | echo -en "\033c\e[3J" #clear screen 1778 | echo -en '\033[?7l' #disable line wrap 1779 | printf '\e[8;41;160t' #set height/width of terminal 1780 | echo "FreshJR_QOS v${version} released ${release}" 1781 | echo "" 1782 | echo 'License' 1783 | echo ' FreshJR_QOS is free to use under the GNU General Public License, version 3 (GPL-3.0).' 1784 | echo ' https://opensource.org/licenses/GPL-3.0' 1785 | echo "" 1786 | echo 'For discussion visit this thread:' 1787 | echo ' https://www.snbforums.com/threads/release-freshjr-adaptive-qos-improvements-custom-rules-and-inner-workings.36836/' 1788 | echo " https://github.com/FreshJR07/FreshJR_QOS (Source Code)" 1789 | echo "" 1790 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 1791 | echo "About" 1792 | echo ' Script Changes Unidentified traffic destination away from "Defaults" into "Others"' 1793 | echo ' Script Changes HTTPS traffic destination away from "Net Control" into "Web Surfing" ' 1794 | echo ' Script Changes Guaranteed Bandwidth per QOS category into logical percentages of upload and download.' 1795 | echo "" 1796 | echo ' Script Repurposes "Defaults" to contain "Game Downloads" ' 1797 | echo ' "Game Downloads" container moved into 6th position' 1798 | echo ' "Lowest Defined" container moved into 7th position' 1799 | echo "" 1800 | echo ' Script includes misc hardcoded rules ' 1801 | echo ' (Wifi Calling) - UDP traffic on remote ports 500 & 4500 moved into VOIP' 1802 | echo ' (Facetime) - UDP traffic on local ports 16384 - 16415 moved into VOIP ' 1803 | echo ' (Usenet) - TCP traffic on remote ports 119 & 563 moved into Downloads ' 1804 | echo ' (Gaming) - Gaming TCP traffic from remote ports 80 & 443 moved into Game Downloads.' 1805 | echo ' (Snapchat) - Moved into Others' 1806 | echo ' (Speedtest.net) - Moved into Downloads' 1807 | echo ' (Google Play) - Moved into Downloads' 1808 | echo ' (Apple AppStore)- Moved into Downloads' 1809 | echo ' (Advertisement) - Moved into Downloads' 1810 | echo ' (VPN Fix) - Router VPN Client upload traffic moved into Downloads instead of whitelisted' 1811 | echo ' (VPN Fix) - Router VPN Client download traffic moved into Downloads instead of showing up in Uploads' 1812 | echo ' (Gaming Manual) - Unidentified traffic for specified devices, not originating from ports 80/443, moved into "Gaming"' 1813 | echo "" 1814 | echo 'Gaming Rule Note' 1815 | echo ' Gaming traffic originating from ports 80 & 443 is primarily downloads & patches (some lobby/login protocols mixed within)' 1816 | echo ' Manually configurable rule will take untracked traffic for specified devices, not originating from server ports 80/443, and place it into Gaming' 1817 | echo ' Use of this gaming rule REQUIRES devices to have a continous static ip assignment && this range needs to be passed into the script' 1818 | echo "" 1819 | echo "How to Use Advanced Functionality" 1820 | echo ' Interactive terminal mode can be accessed by running the -menu command:' 1821 | echo ' (interactive mode) : /jffs/scripts/FreshJR_QOS -menu' 1822 | echo ' Custom rules can be created via the WebUI OR directly accessed by running the -rules command:' 1823 | echo ' (custom rules) : /jffs/scripts/FreshJR_QOS -rules' 1824 | echo ' Bandwidth allocation per category can be adjusted via the WebUI OR directly accessed by running the -rates command:' 1825 | echo ' (custom rates) : /jffs/scripts/FreshJR_QOS -rates' 1826 | echo "" 1827 | echo 'Development' 1828 | echo ' Tested with ASUS AC-68U, FW384.9, using Adaptive QOS with Manual Bandwidth Settings' 1829 | echo ' Copyright (C) 2017-2019 FreshJR - All Rights Reserved ' 1830 | echo -en '\033[?7h' #enable line wrap 1831 | } 1832 | 1833 | update(){ 1834 | 1835 | echo -en "\033c\e[3J" #clear screen 1836 | echo -en '\033[?7l' #disable line wrap 1837 | printf '\e[8;30;120t' #set height/width of terminal 1838 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 1839 | echo "Checking for updates" 1840 | echo "" 1841 | url="https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh" 1842 | remotever=$(curl -fsN --retry 3 ${url} | grep "^version=" | sed -e s/version=//) 1843 | 1844 | if [ "$version" != "$remotever" ]; then 1845 | echo " FreshJR QOS v${remotever} is now available!" 1846 | echo "" 1847 | echo -n " Would you like to update now? [1=Yes 2=No] : " 1848 | read yn 1849 | echo "" 1850 | if ! [ "${yn}" == "1" ] ; then 1851 | echo -e "\033[1;31;7m No Changes have been made \033[0m" 1852 | echo "" 1853 | return 0 1854 | fi 1855 | else 1856 | echo " You have the latest version installed" 1857 | echo -n " Would you like to overwrite your existing installation anyway? [1=Yes 2=No] : " 1858 | read yn 1859 | echo "" 1860 | if ! [ "${yn}" == "1" ] ; then 1861 | echo -e "\033[1;31;7m No Changes have been made \033[0m" 1862 | echo "" 1863 | return 0 1864 | fi 1865 | fi 1866 | 1867 | echo -e "Installing: FreshJR_QOS_v${remotever}" 1868 | echo "" 1869 | echo "Curl Output:" 1870 | curl "https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh" -o /jffs/scripts/FreshJR_QOS --create-dirs && curl "https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QoS_Stats.asp" -o "${webpath}" && sh /jffs/scripts/FreshJR_QOS -install 1871 | exit 1872 | } 1873 | 1874 | prompt_restart(){ 1875 | echo "" 1876 | echo -en " Would you like to \033[1;32m[Restart QoS]\033[0m for modifications to take effect? [1=Yes 2=No] : " 1877 | read yn 1878 | if [ "${yn}" == "1" ] ; then 1879 | if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #RMerlin install 1880 | service "restart_qos;restart_firewall" 1881 | else #Stock Install 1882 | service "restart_qos;restart_firewall" 1883 | cru a FreshJR_QOS_run_once "* * * * * /jffs/scripts/FreshJR_QOS -mount &" #cron task so keeps running after terminal is closed 1884 | fi 1885 | echo "" 1886 | else 1887 | echo "" 1888 | if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #RMerlin install 1889 | echo -e "\033[1;31;7m Remember: [ Restart QOS ] for modifications to take effect \033[0m" 1890 | echo "" 1891 | else #Stock install 1892 | echo -e "\033[1;31;7m Remember: [ Restart Router ] for modifications to take effect \033[0m" 1893 | echo "" 1894 | fi 1895 | fi 1896 | } 1897 | 1898 | menu(){ 1899 | read_nvram 1900 | echo -en "\033c\e[3J" #clear screen 1901 | echo -en '\033[?7l' #disable line wrap 1902 | printf '\e[8;30;120t' #set height/width of terminal 1903 | echo -e "\033[1;32mFreshJR QOS v${version} released ${release} \033[0m" 1904 | echo " (1) about explain functionality" 1905 | echo " (2) update check for updates " 1906 | echo "" 1907 | echo " (3) QoS rules QoS rules (user defined)" 1908 | echo " (4) QoS rates QoS rates (bandwidth allocation per category)" 1909 | echo "" 1910 | echo " (5) debug traffic control parameters" 1911 | echo " (6) debug2 parsed nvram parameters" 1912 | echo "" 1913 | echo " (u) uninstall uninstall script" 1914 | echo "" 1915 | echo " (e) exit" 1916 | echo "" 1917 | echo " Current Setup:" 1918 | echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst" 1919 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")" 1920 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")" 1921 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")" 1922 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")" 1923 | printf ' Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming" 1924 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")" 1925 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")" 1926 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")" 1927 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")" 1928 | echo "" 1929 | echo -en '\033[?7h' #enable line wrap 1930 | echo -n "Make a selection: " 1931 | read input 1932 | case $input in 1933 | '1') 1934 | about 1935 | read -n 1 -s -r -p "(Press any key to return)" 1936 | echo -en "\033c" #clear screen 1937 | ;; 1938 | '2') 1939 | update 1940 | read -n 1 -s -r -p "(Press any key to return)" 1941 | echo -en "\033c" #clear screen 1942 | ;; 1943 | '3') 1944 | rules 1945 | read -n 1 -s -r -p "(Press any key to return)" 1946 | echo -en "\033c" #clear screen 1947 | ;; 1948 | '4') 1949 | rates 1950 | read -n 1 -s -r -p "(Press any key to return)" 1951 | echo -en "\033c" #clear screen 1952 | ;; 1953 | '5') 1954 | debug 1955 | echo "" 1956 | read -n 1 -s -r -p "(Press any key to return)" 1957 | echo -en "\033c" #clear screen 1958 | ;; 1959 | '6') 1960 | debug2 1961 | echo "" 1962 | read -n 1 -s -r -p "(Press any key to return)" 1963 | echo -en "\033c" #clear screen 1964 | ;; 1965 | 'u'|'U') 1966 | clear 1967 | echo -e "\033[1;32mFreshJR QOS v${version} released ${release} \033[0m" 1968 | echo "" 1969 | echo -en " Confirm you want to \033[1;32m[uninstall]\033[0m FreshJR_QOS [1=Yes 2=No] : " 1970 | read yn 1971 | if [ "${yn}" == "1" ] ; then 1972 | echo "" 1973 | sh /jffs/scripts/FreshJR_QOS -uninstall 1974 | echo "" 1975 | exit 1976 | fi 1977 | echo "" 1978 | echo -e "\033[1;31;7m FreshJR QOS has NOT been uninstalled \033[0m" 1979 | echo "" 1980 | read -n 1 -s -r -p "(Press any key to return)" 1981 | echo -en "\033c" #clear screen 1982 | ;; 1983 | 'e'|'E') 1984 | echo -en "\033[1A\r\033[0K" 1985 | return 1986 | ;; 1987 | 1988 | esac 1989 | menu 1990 | } 1991 | 1992 | ##alternative install for (non-RMerlin) firmware 1993 | stock_install(){ 1994 | if [ "$(nvram get script_usbmount)" != "/jffs/scripts/script_usbmount" ] ; then 1995 | echo "" 1996 | echo -e "\033[1;32m Creating environment to trigger scripts post USB Mount \033[0m" 1997 | nvram set script_usbmount="/jffs/scripts/script_usbmount" 1998 | nvram commit 1999 | fi 2000 | 2001 | if [ -f /jffs/scripts/script_usbmount ] ; then #check if script_usbmount exists 2002 | if grep -q "#!/bin/sh" /jffs/scripts/script_usbmount ; then #check if script_usbmount header is correct 2003 | : #if header is correct, do nothing 2004 | else #if header is incorrect, fix header 2005 | echo " Detected improper header in script_usbmount, fixing header" 2006 | sed -i "1i #!/bin/sh" /jffs/scripts/script_usbmount 2007 | chmod 0755 /jffs/scripts/script_usbmount 2008 | fi 2009 | 2010 | sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2011 | echo '/jffs/scripts/FreshJR_QOS mount &' >> /jffs/scripts/script_usbmount 2012 | 2013 | else #if script_usbmount did not exist then set it up entirely 2014 | echo " Creating script_usbmount in /jffs/scripts/" 2015 | echo " Placing FreshJR_QOS into script_usbmount" 2016 | echo "#!/bin/sh" > /jffs/scripts/script_usbmount 2017 | echo '/jffs/scripts/FreshJR_QOS mount &' >> /jffs/scripts/script_usbmount 2018 | chmod 0755 /jffs/scripts/script_usbmount 2019 | fi 2020 | 2021 | echo -e "\033[1;32mFreshJR QOS v${version} has been installed \033[0m" 2022 | echo -e "\033[1;32m make sure a USB storage device is plugged in and \033[0m" 2023 | echo -e "\033[1;31;7m [ reboot router ] to finalize installation\033[0m" 2024 | echo "" 2025 | } 2026 | 2027 | #Main program here, will execute different things depending on arguments 2028 | arg1="$(echo "$1" | tr -d "-")" 2029 | case "$arg1" in 2030 | 'start'|'check'|'mount') ##RAN ON FIREWALL-START OR CRON TASK, (RAN ONLY POST USB MOUNT IF USING STOCK ASUS FIRMWARE) 2031 | cru a FreshJR_QOS "30 3 * * * /jffs/scripts/FreshJR_QOS -check" #makes sure daily check if active 2032 | cru d FreshJR_QOS_run_once #(used for stock firmware to trigger script and have it run after terminal is closed when making changes) 2033 | 2034 | if [ "$(nvram get qos_enable)" == "1" ] ; then 2035 | for pid in $(pidof FreshJR_QOS); do 2036 | if [ $pid != $$ ]; then 2037 | if ! [ "$(ps -w | grep "${pid}.*\(install\|menu\|rules\|rates\)" | grep -v "grep")" ] ; then #kill all previous instances of FreshJR_QOS (-install, -menu, -rules, -rates instances are whitelisted) 2038 | kill $pid 2039 | logger -t "adaptive QOS" -s "Delayed Start Canceled" 2040 | fi 2041 | fi 2042 | done 2043 | 2044 | ##check if should mount QoS_stats page 2045 | if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then 2046 | buildno="$(nvram get buildno)"; #Example "User12 v17.2 Beta4" 2047 | if [ "$(echo ${buildno} | tr -cd '.' | wc -c)" -ne 0 ] ; then #if has decimal 2048 | CV="$(echo ${buildno} | cut -d "." -f 1 | grep -o '[0-9]\+' | tail -1)" #get first number before decimal --> 17 2049 | MV="$(echo ${buildno} | cut -d "." -f 2 | grep -o '[0-9]\+' | head -1)" #get first number after decimal --> 2 2050 | else 2051 | CV="$(echo ${buildno} | grep -o '[0-9]\+' | head -1)" #get first number --> 17 2052 | MV="0" 2053 | fi 2054 | 2055 | if [ "${CV}" -ge "382" ] ; then 2056 | if ! [ "${webpath}" -ef "/www/QoS_Stats.asp" ] ; then 2057 | mount -o bind "${webpath}" /www/QoS_Stats.asp 2058 | fi 2059 | #elif [ "${CV}" = "384" ] && [ ${MV} -ge "9" ] ; then 2060 | fi 2061 | fi 2062 | 2063 | read_nvram #needs to be set before parse_iptablerule or custom rates 2064 | 2065 | if [ "$arg1" == "start" ] ; then 2066 | ##iptables rules will only be reapplied on firewall "start" due to receiving interface name 2067 | wan="${2}" 2068 | if [ -z "$wan" ] ; then 2069 | wan="eth0" 2070 | fi 2071 | 2072 | parse_iptablerule "${e1}" "${e2}" "${e3}" "${e4}" "${e5}" "${e6}" "${e7}" ip1_down ip1_up ##last two arguments are variables that get set "ByRef" 2073 | parse_iptablerule "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" "${f6}" "${f7}" ip2_down ip2_up 2074 | parse_iptablerule "${g1}" "${g2}" "${g3}" "${g4}" "${g5}" "${g6}" "${g7}" ip3_down ip3_up 2075 | parse_iptablerule "${h1}" "${h2}" "${h3}" "${h4}" "${h5}" "${h6}" "${h7}" ip4_down ip4_up 2076 | 2077 | iptable_down_rules 2>&1 | logger -t "adaptive QOS" 2078 | iptable_up_rules 2>&1 | logger -t "adaptive QOS" 2079 | 2080 | logger -t "adaptive QOS" -s -- "TC Modification Delayed Start (5min)" 2081 | sleep 300s 2082 | fi 2083 | 2084 | 2085 | if [ "$arg1" == "mount" ] ; then 2086 | logger -t "adaptive QOS" -s -- "--Post USB Mount-- Delayed Start (10min)" 2087 | sleep 600s 2088 | 2089 | fi 2090 | 2091 | current_undf_rule="$(tc filter show dev br0 | grep -v "/" | grep "000ffff" -B1)" 2092 | undf_flowid=$(echo $current_undf_rule | grep -o "flowid.*" | cut -d" " -f2 | head -1) 2093 | undf_prio=$(echo $current_undf_rule | grep -o "pref.*" | cut -d" " -f2 | head -1) 2094 | #if TC modifcations have no been applied then run modification script 2095 | #eg (if rule setting unidentified traffic to 1:17 exists) --> run modification script 2096 | if [ "${undf_flowid}" == "1:17" ] ; then 2097 | if [ "$arg1" == "check" ] ; then 2098 | logger -t "adaptive QOS" -s "Scheduled Persistence Check -> Reapplying Changes" 2099 | fi 2100 | 2101 | #this section is only used stock ASUS firmware. It will will evaluate on (-mount && -check) parameters only on STOCK firmware 2102 | if [ "$(nvram get script_usbmount)" == "/jffs/scripts/script_usbmount" ] && [ "$arg1" != "start" ] ; then 2103 | wan="$(iptables -vL -t mangle | grep -m 1 "BWDPI_FILTER" | tr -s ' ' | cut -d ' ' -f 7)" #try to detect upload interface automatically 2104 | if [ -z "$wan" ] ; then 2105 | wan="eth0" 2106 | fi 2107 | parse_iptablerule "${e1}" "${e2}" "${e3}" "${e4}" "${e5}" "${e6}" "${e7}" ip1_down ip1_up ##last two arguments are variables that get set "ByRef" 2108 | parse_iptablerule "${f1}" "${f2}" "${f3}" "${f4}" "${f5}" "${f6}" "${f7}" ip2_down ip2_up 2109 | parse_iptablerule "${g1}" "${g2}" "${g3}" "${g4}" "${g5}" "${g6}" "${g7}" ip3_down ip3_up 2110 | parse_iptablerule "${h1}" "${h2}" "${h3}" "${h4}" "${h5}" "${h6}" "${h7}" ip4_down ip4_up 2111 | 2112 | iptable_down_rules 2>&1 | logger -t "adaptive QOS" 2113 | iptable_up_rules 2>&1 | logger -t "adaptive QOS" 2114 | fi 2115 | 2116 | set_tc_variables #needs to be set before parse_tcrule 2117 | ##last two arguments are variables that get set "ByRef" 2118 | parse_tcrule "${r1}" "${d1}" tc1_down tc1_up 2119 | parse_tcrule "${r2}" "${d2}" tc2_down tc2_up 2120 | parse_tcrule "${r3}" "${d3}" tc3_down tc3_up 2121 | parse_tcrule "${r4}" "${d4}" tc4_down tc4_up 2122 | tc_redirection_down_rules "$undf_prio" 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger 2123 | tc_redirection_up_rules "$undf_prio" 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger 2124 | 2125 | if [ "$ClassesPresent" -lt "8" ] ; then 2126 | logger -t "adaptive QOS" -s "Adaptive QOS not fully done setting up prior to modification script" 2127 | logger -t "adaptive QOS" -s "(Skipping class modification, delay trigger time period needs increase)" 2128 | else 2129 | if [ "$DownCeil" -gt "500" ] && [ "$UpCeil" -gt "500" ] ; then 2130 | custom_rates 2>&1 | logger -t "adaptive QOS" #forwards terminal output & errors to logger 2131 | fi 2132 | fi 2133 | 2134 | else 2135 | if [ "$arg1" == "check" ] ; then 2136 | logger -t "adaptive QOS" -s "Scheduled Persistence Check -> No modifications necessary" 2137 | else 2138 | logger -t "adaptive QOS" -s "No modifications necessary" 2139 | fi 2140 | fi 2141 | fi 2142 | ;; 2143 | 'install'|'enable') ## INSTALLS AND TURNS ON SCRIPT 2144 | printf '\e[8;30;120t' #set height/width of terminal 2145 | clear 2146 | chmod 0755 /jffs/scripts/FreshJR_QOS 2147 | if grep -qs "FreshJR_QOS" /jffs/scripts/init-start ; then 2148 | sed -i '/FreshJR_QOS/d' /jffs/scripts/init-start 2>/dev/null 2149 | fi 2150 | if [ "/jffs/scripts/FreshJR_QOS_fakeTC" -ef "/bin/tc" ] || [ "/jffs/scripts/FreshJR_QOS_fakeTC" -ef "/usr/sbin/tc" ] ; then ##uninstall previous version FreshJR_QOS_fakeTC if not already uninstalled 2151 | 2152 | echo "Old version of FreshJR_QOS_fast(fakeTC) has been Detected" 2153 | 2154 | if [ -e "/bin/tc" ] ; then 2155 | umount /bin/tc &> /dev/null #suppresses error if present 2156 | mount -o bind /usr/sbin/faketc /bin/tc 2157 | elif [ -e "/usr/sbin/tc" ] ; then 2158 | umount /usr/sbin/tc &> /dev/null #suppresses error if present 2159 | mount -o bind /usr/sbin/faketc /usr/sbin/tc 2160 | fi 2161 | 2162 | rm -f /jffs/scripts/FreshJR_QOS_fakeTC 2163 | nvram unset qos_downrates 2164 | nvram unset qos_uprates 2165 | nvram commit 2166 | 2167 | if [ "/usr/sbin/faketc" -ef "/usr/sbin/tc" ] || [ "/usr/sbin/faketc" -ef "/bin/tc" ] ; then 2168 | echo "Old version of FreshJR_QOS_fast(fakeTC) has been Successfully Uninstalled" 2169 | else 2170 | echo "FreshJR_QOS_fast(fakeTC) Uninstall Process has been Initiated " 2171 | echo -e "\033[1;31;7m Please [ reboot router ] to finish the uninstall process \033[0m" 2172 | echo -e "\033[1;31;7m Rerun this install procedure after system reboot \033[0m" 2173 | exit 0 2174 | fi 2175 | fi 2176 | 2177 | if [ "$(uname -o)" != "ASUSWRT-Merlin" ] ; then ##GIVE USER CHOICE TO RUN STOCK INSTALL IF Non-RMerlin FIRMWARE detected 2178 | echo -e "\033[1;31m Non-RMerlin Firmware Detected \033[0m" 2179 | echo -e -n "\033[1;31m Is this installation for (Stock / Default / Unmodified) Asus firmware? [1=Yes 2=No] : \033[0m" # Display prompt in red 2180 | read yn 2181 | echo "" 2182 | case $yn in 2183 | '1') 2184 | sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null 2185 | stock_install; 2186 | exit 0 2187 | ;; 2188 | '2') 2189 | sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null 2190 | echo -e "\033[1;32m Installing RMerlin version of the script \033[0m" # Display prompt in red 2191 | echo "" 2192 | break 2193 | ;; 2194 | *) 2195 | echo "Invalid Option" 2196 | echo "ABORTING INSTALLATION " 2197 | exit 0 2198 | ;; 2199 | esac 2200 | fi 2201 | 2202 | if [ -f /jffs/scripts/firewall-start ] ; then #check if firewall-start exists 2203 | if grep -q "#!/bin/sh" /jffs/scripts/firewall-start ; then #check if firewall-start header is correct 2204 | : #if header is correct, do nothing 2205 | else #if header is incorrect, fix header 2206 | echo "Detected improper header in firewall-start, fixing header" 2207 | sed -i "1i #!/bin/sh" /jffs/scripts/firewall-start 2208 | chmod 0755 /jffs/scripts/firewall-start 2209 | fi 2210 | 2211 | if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then #check if FreshJR_QOS is present as item in firewall start 2212 | : #if FreshJR_QOS is present do nothing 2213 | else #if not, appened it to the last line (also delete any previously formated entry) 2214 | echo "Placing FreshJR_QOS entry into firewall-start" 2215 | sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2216 | echo '/jffs/scripts/FreshJR_QOS -start $1 & ' >> /jffs/scripts/firewall-start 2217 | fi 2218 | else #if firewall-start does not exist then set it up entirely 2219 | echo "Firewall-start not detected, creating firewall-start" 2220 | echo "Placing FreshJR_QOS entry into firewall-start" 2221 | echo "#!/bin/sh" > /jffs/scripts/firewall-start 2222 | echo '/jffs/scripts/FreshJR_QOS -start $1 & ' >> /jffs/scripts/firewall-start 2223 | chmod 0755 /jffs/scripts/firewall-start 2224 | fi 2225 | cru a FreshJR_QOS "30 3 * * * /jffs/scripts/FreshJR_QOS -check" 2226 | 2227 | if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then #Mounts webpage on RMerlin v382+ 2228 | buildno="$(nvram get buildno)"; #Example "User12 v17.2 Beta4" 2229 | if [ "$(echo ${buildno} | tr -cd '.' | wc -c)" -ne 0 ] ; then #if has decimal 2230 | CV="$(echo ${buildno} | cut -d "." -f 1 | grep -o '[0-9]\+' | tail -1)" #get first number before decimal --> 17 2231 | MV="$(echo ${buildno} | cut -d "." -f 2 | grep -o '[0-9]\+' | head -1)" #get first number after decimal --> 2 2232 | else 2233 | CV="$(echo ${buildno} | grep -o '[0-9]\+' | head -1)" #get first number --> 17 2234 | MV="0" 2235 | fi 2236 | 2237 | if [ "${CV}" -ge "382" ] ; then 2238 | if ! [ "${webpath}" -ef "/www/QoS_Stats.asp" ] ; then 2239 | mount -o bind "${webpath}" /www/QoS_Stats.asp 2240 | fi 2241 | #elif [ "${CV}" = "384" ] && [ ${MV} -ge "9" ] ; then 2242 | fi 2243 | fi 2244 | 2245 | #shortcut to launching FreshJR_QOS (/usr/bin was readonly) 2246 | alias freshjr="sh /jffs/scripts/FreshJR_QOS -menu" 2247 | alias freshjrqos="sh /jffs/scripts/FreshJR_QOS -menu" 2248 | alias freshjr_qos="sh /jffs/scripts/FreshJR_QOS -menu" 2249 | alias FreshJR_QOS="sh /jffs/scripts/FreshJR_QOS -menu" 2250 | sed -i '/fresh/d' /jffs/configs/profile.add 2>/dev/null 2251 | echo 'alias freshjr="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add 2252 | echo 'alias freshjrqos="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add 2253 | echo 'alias freshjr_qos="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add 2254 | echo 'alias FreshJR_QOS="sh /jffs/scripts/FreshJR_QOS -menu"' >> /jffs/configs/profile.add 2255 | 2256 | 2257 | echo -e "\033[1;32mFreshJR QOS v${version} has been installed \033[0m" 2258 | echo "" 2259 | echo -n " Advanced configuration available via: " 2260 | if [ "$(uname -o)" == "ASUSWRT-Merlin" ] ; then 2261 | if [ -e "/jffs/scripts/amtm" ] ; then 2262 | echo -e "\033[1;32m[ WebUI ]\033[0m or \033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m or \033[1;32m[ amtm ]\033[0m " 2263 | else 2264 | echo -e "\033[1;32m[ WebUI ]\033[0m or \033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m " 2265 | fi 2266 | else 2267 | echo -e "\033[1;32m[ /jffs/scripts/FreshJR_QOS -menu ]\033[0m " 2268 | fi 2269 | 2270 | [ "$(nvram get qos_enable)" == "1" ] && prompt_restart 2271 | ;; 2272 | 'uninstall') ## UNINSTALLS SCRIPT AND DELETES FILES 2273 | sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null #remove FreshJR_QOS from firewall start 2274 | sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null #remove FreshJR_QOS from script_usbmount - only used on stock ASUS firmware installs 2275 | sed -i '/freshjr/d' /jffs/configs/profile.add 2>/dev/null #remove aliases used to launch interactive mode 2276 | sed -i '/FreshJR/d' /jffs/configs/profile.add 2>/dev/null 2277 | cru d FreshJR_QOS 2278 | rm -f /jffs/scripts/FreshJR_QOS 2279 | 2280 | umount /www/QoS_Stats.asp &> /dev/null #suppresses error if present 2281 | mount -o bind /www/QoS_Stats.asp /www/QoS_Stats.asp 2282 | umount /www/QoS_Stats.asp &> /dev/null 2283 | rm -f "${webpath}" 2284 | 2285 | if [ "$(nvram get script_usbmount)" == "/jffs/scripts/script_usbmount" ] ; then #only used on stock ASUS firmware installs 2286 | nvram unset script_usbmount 2287 | fi 2288 | nvram set fb_comment="" 2289 | nvram set fb_email_dbg="" 2290 | nvram commit 2291 | echo -e "\033[1;32m FreshJR QOS has been uninstalled \033[0m" 2292 | ;; 2293 | 'disable') ## TURNS OFF SCRIPT BUT KEEP FILES 2294 | sed -i '/FreshJR_QOS/d' /jffs/scripts/firewall-start 2>/dev/null 2295 | sed -i '/FreshJR_QOS/d' /jffs/scripts/script_usbmount 2>/dev/null 2296 | cru d FreshJR_QOS 2297 | umount /www/QoS_Stats.asp &> /dev/null #suppresses error if present 2298 | mount -o bind /www/QoS_Stats.asp /www/QoS_Stats.asp 2299 | umount /www/QoS_Stats.asp &> /dev/null 2300 | ;; 2301 | 'debug') 2302 | debug 2303 | ;; 2304 | 'debug2') 2305 | debug2 2306 | ;; 2307 | 'debug3') 2308 | debug3 2309 | ;; 2310 | 'appdb') 2311 | appdb "$2" 2312 | ;; 2313 | 'gameip') 2314 | read_nvram 2315 | gameip "$2" 2316 | ;; 2317 | 'rules') 2318 | read_nvram 2319 | rules 2320 | ;; 2321 | 'rates') 2322 | read_nvram 2323 | rates 2324 | ;; 2325 | 'about') 2326 | about 2327 | ;; 2328 | 'update') 2329 | update 2330 | ;; 2331 | 'menu') 2332 | menu 2333 | ;; 2334 | 'isinstalled') 2335 | if grep -q -x '/jffs/scripts/FreshJR_QOS -start $1 & ' /jffs/scripts/firewall-start ; then 2336 | exit 0 #script IS installed 2337 | else 2338 | exit 1 #script in NOT installed 2339 | fi 2340 | ;; 2341 | 'isuptodate') 2342 | url="https://raw.githubusercontent.com/FreshJR07/FreshJR_QOS/master/FreshJR_QOS.sh" 2343 | remotever=$(curl -fsN --retry 3 ${url} | grep "^version=" | sed -e s/version=//) 2344 | if [ "$version" == "$remotever" ]; then 2345 | exit 0 #script IS current 2346 | else 2347 | exit 1 #script is NOT up to date 2348 | fi 2349 | 2350 | ;; 2351 | *) 2352 | read_nvram 2353 | echo -en "\033c\e[3J" #clear screen 2354 | echo -en '\033[?7l' #disable line wrap 2355 | # printf '\e[8;30;120t' #set height/width of terminal 2356 | echo -e "\033[1;32mFreshJR QOS v${version} \033[0m" 2357 | echo -e "\033[1;32mreleased ${release} \033[0m" 2358 | echo "" 2359 | echo "You have inputted an UNRECOGNIZED COMMAND" 2360 | echo "" 2361 | echo " Available commands:" 2362 | echo "" 2363 | echo " FreshJR_QOS -about explains functionality" 2364 | echo " FreshJR_QOS -update checks for updates " 2365 | echo "" 2366 | echo " FreshJR_QOS -install install script" 2367 | echo " FreshJR_QOS -uninstall uninstall script && delete from disk " 2368 | echo "" 2369 | echo " FreshJR_QOS -enable enable script " 2370 | echo " FreshJR_QOS -disable disable script but do not delete from disk" 2371 | echo "" 2372 | echo " FreshJR_QOS -debug print traffic control parameters" 2373 | echo " FreshJR_QOS -debug2 print parsed nvram parameters" 2374 | echo "" 2375 | echo ' FreshJR_QOS -appdb "App Name" looks up mark for specifed application' 2376 | echo "" 2377 | echo " FreshJR_QOS -rules create/modify custom rules" 2378 | echo " FreshJR_QOS -rates modify bandwidth allocations" 2379 | echo "" 2380 | echo ' FreshJR_QOS -menu interactive main menu' 2381 | echo "" 2382 | echo " Current Setup:" 2383 | echo " Local IP Remote IP Proto Local Port Remote Port Mark Dst" 2384 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$e1" "$e2" "$e3" "$e4" "$e5" "$e6" "$([ -z $e7 ] || echo "--> $(dst_2_name $e7)")" 2385 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$([ -z $f7 ] || echo "--> $(dst_2_name $f7)")" 2386 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$g1" "$g2" "$g3" "$g4" "$g5" "$g6" "$([ -z $g7 ] || echo "--> $(dst_2_name $g7)")" 2387 | printf ' Rule %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "$h1" "$h2" "$h3" "$h4" "$h5" "$h6" "$([ -z $h7 ] || echo "--> $(dst_2_name $h7)")" 2388 | printf ' Gameip %-19s %-19s %-6s %-14s %-14s %-7s %-10s\n' "${gameCIDR}" "" "$([ -z $gameCIDR ] || echo "both")" "" "$([ -z $gameCIDR ] || echo "!80:443")" "$([ -z $gameCIDR ] || echo "000000")" "--> Gaming" 2389 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r1)" "$r1" "$([ -z $d1 ] || echo "--> $(dst_2_name $d1)")" 2390 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r2)" "$r2" "$([ -z $d2 ] || echo "--> $(dst_2_name $d2)")" 2391 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r3)" "$r3" "$([ -z $d3 ] || echo "--> $(dst_2_name $d3)")" 2392 | printf ' Appdb %-44s %-7s %-10s\n' "$(mark_2_name $r4)" "$r4" "$([ -z $d4 ] || echo "--> $(dst_2_name $d4)")" 2393 | echo "" 2394 | echo -en '\033[?7h' #enable line wrap 2395 | ;; 2396 | esac 2397 | --------------------------------------------------------------------------------