Last active
July 23, 2024 12:56
-
-
Save smhdhsn/fe2c9f334e3d0db1f6102991ddc694a0 to your computer and use it in GitHub Desktop.
shecan.ir configurator.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/bash -e | |
##################################################### | |
# DNS configurator # | |
##################################################### | |
# Responds to a list of syscall. | |
trap "error 'Exiting now...'" SIGINT SIGQUIT | |
# CLI options (IRREPLACEABLE). | |
readonly bold=`tput bold` | |
readonly reset=`tput sgr0` | |
readonly red=`tput setaf 1` | |
readonly blue=`tput setaf 4` | |
readonly cyan=`tput setaf 6` | |
readonly grey=`tput setaf 8` | |
# Prints out a given message. | |
# Arguments: | |
# $1 - Message to print | |
# $2 - Optional flag to determine if the message should be suffixed with \r | |
function out { | |
if [[ $2 ]]; then | |
echo -ne "${1}\r" | |
else | |
echo -ne "${1}\n" | |
fi | |
} | |
# Modifies a success message. | |
# Arguments: | |
# $1 - Success message | |
# $2 - Optional flag to determine if the message should be prefixed | |
# $3 - Optional flag for line ending | |
function success { | |
local prefix='[+] ' | |
if [[ $2 ]]; then | |
msg="${cyan}${bold}${prefix}${reset}${blue}${1}${reset}" | |
else | |
msg="${blue}${1}${reset}" | |
fi | |
out "$msg" $3 >> /dev/stdout | |
} | |
# Modifies an info message. | |
# Arguments: | |
# $1 - Info message | |
# $2 - Optional flag to determine if the message should be prefixed | |
# $3 - Optional flag for line ending | |
function info { | |
local prefix='[*] ' | |
if [[ $2 ]]; then | |
msg="${cyan}${bold}${prefix}${reset}${grey}${1}${reset}" | |
else | |
msg="${grey}${1}${reset}" | |
fi | |
out "$msg" $3 >> /dev/stdout | |
} | |
# Modifies an error message. | |
# Arguments: | |
# $1 - Error message | |
# $2 - Optional flag to determine if the message should be prefixed | |
# $3 - Optional flag for line ending | |
function error { | |
local prefix='[-] ' | |
if [[ $2 ]]; then | |
msg="${cyan}${bold}${prefix}${reset}${red}${1}${reset}" | |
else | |
msg="${red}${1}${reset}" | |
fi | |
out "$msg" $3 >> /dev/stderr \ | |
&& exit 1 | |
} | |
# Prints out the usage guide of this script. | |
function usage { | |
echo -e "Usage: $0 OPTION ARGUMENT [OPTION ARGUMENT]... | |
-a\tRead configurations from specified address. | |
-f\tChoose file to extract configurations from. | |
-i\tSpecify hook to extract configurations with. | |
-m\tChange application flow. [${FLOW_ADD}, ${FLOW_REMOVE}, ${FLOW_UPDATE}, ${FLOW_STATUS}]" >> /dev/stdout | |
} | |
# Makes print functions irreplaceable. | |
readonly -f usage success error info out | |
# RegEx pattern for validating IPv4. (IRREPLACEABLE) | |
readonly ipRegEx="((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])" | |
# Default path to DNS configurations. | |
readonly configFilePath="/etc/resolv.conf" | |
# DNS configurator's identifier. (IRREPLACEABLE) | |
readonly appFlag='#DNS_CONFIGURATOR' | |
# Key for configuring a DNS. | |
readonly configKey="nameserver" | |
# This section holds keys of application's flow. | |
# status: Checks if any configurations are already applied by this script. | |
# update: Removes old configurations and adds new configurations. | |
# remove: Removes old configurations. | |
# add: Adds new configurations. | |
readonly FLOW_STATUS="status" | |
readonly FLOW_UPDATE="update" | |
readonly FLOW_REMOVE="remove" | |
readonly FLOW_ADD="add" | |
# This section holds keys of application's source of configurations. | |
# file: Reads configurations from file. | |
# url: Extracts configurations from url. | |
readonly SOURCE_FILE="file" | |
readonly SOURCE_URL="url" | |
# Default url to get DNS configurations from. | |
url='https://shecan.ir' | |
# Default hook for catching DNS configurations. | |
hook='shecan-dns-ips' | |
# Default application's source form extracting configurations. | |
configSource=$SOURCE_URL | |
# Default application flow. | |
flow=$FLOW_ADD | |
# Gets the program's source of configurations based on input. | |
# Arguments: | |
# $1 - Source value (URL or file path) | |
# $2 - Source type (file or URL) | |
function getSource { | |
configSource=$2 | |
if [[ $configSource == $SOURCE_FILE ]]; then | |
configFile=$1 | |
elif [[ $configSource == $SOURCE_URL ]]; then | |
url=$1 | |
fi | |
} | |
# Gets the program's flow based on input. | |
# Arguments: | |
# $1 - Flow value (add, remove, update, status) | |
function getFlow { | |
if grep -qE "\b(${FLOW_ADD}|${FLOW_REMOVE}|${FLOW_UPDATE}|${FLOW_STATUS})\b" <<< $1; then | |
flow=$1 | |
else | |
usage; exit 1 | |
fi | |
} | |
# Writes given addresses to the local DNS configuration file. | |
# Arguments: | |
# $@ - List of DNS addresses | |
function write { | |
for address in $@; do | |
if ! grep -Exq "${configKey}\s+${address}\s+${appFlag}$" $configFilePath; then | |
sudo sed -i "$(grep -n "${configKey}" ${configFilePath} | cut -f 1 -d ':' | head -n 1)i\\${configKey} ${address} \\t${appFlag}" $configFilePath | |
fi | |
done | |
} | |
# Removes old DNS configurations from local DNS configuration file. (Identifies old configurations with app flag) | |
function remove { | |
sudo sed -i "/${appFlag}$/d" $configFilePath | |
} | |
# Makes managing functions irreplaceable. | |
readonly -f getSource getFlow write remove | |
# Gets arguments from input. | |
while getopts "a:f:i:m:h" arg; do | |
case $arg in | |
a ) | |
getSource $OPTARG $SOURCE_URL | |
;; | |
f ) | |
getSource $OPTARG $SOURCE_FILE | |
;; | |
i ) | |
hook=$OPTARG | |
;; | |
m ) | |
getFlow $OPTARG | |
;; | |
h ) | |
usage; exit | |
;; | |
* ) | |
usage; exit 1 | |
;; | |
esac | |
done | |
# Checks if the chosen flow requires removing old configurations. | |
if [[ $flow == $FLOW_UPDATE || $flow == $FLOW_REMOVE ]]; then | |
{ # This section removes old configurations from local DNS configuration file. | |
remove \ | |
&& success "Old configurations have been removed." true | |
} || { | |
error "Error on removing old configuration files." true | |
} | |
# If the flow is 'off' the application needs to be terminated. | |
if [[ $flow == $FLOW_REMOVE ]]; then | |
info "All configurations has been removed."; exit | |
fi | |
elif [[ $flow == $FLOW_STATUS ]]; then | |
if grep -Fq "${appFlag}" "${configFilePath}"; then | |
info "Configurations are ${blue}active${reset}."; exit | |
else | |
info "Configurations are ${red}inactive${reset}."; exit | |
fi | |
fi | |
# This section is responsible for chosing the source of configurations [URL, FILE]. | |
if [[ $configSource == $SOURCE_FILE ]]; then | |
{ # This section fetches payload from FILE. | |
info "Reading file..." true true \ | |
&& payload=$(cat $configFile) \ | |
&& success "File has been read." true | |
} || { | |
error "Error on reading file." true | |
} | |
elif [[ $configSource == $SOURCE_URL ]]; then | |
{ # This section fetches payload from URL. | |
info "Fetching payload..." true true \ | |
&& payload=$(curl -sX GET ${url} | grep ${hook}) \ | |
&& success "Payload has been fetched." true | |
} || { | |
error "Error on fetching payload." true | |
} | |
fi | |
{ # This section extracts DNS configurations from payload. | |
info "Extracting configurations..." true true \ | |
&& addresses=$(grep -oE ${ipRegEx} <<< ${payload}) \ | |
&& success "Configurations have been extracted." true | |
} || { | |
error "Error on extracting configurations." true | |
} | |
{ # This section writes new configurations to the local DNS configuration file. | |
write $addresses \ | |
&& success "Local DNS configuration file has been updated." true | |
} || { | |
error "Error on editing local DNS configuration file." true | |
} | |
info "Enjoy your freedom :)" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment