123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #!/bin/sh
- # Copyright (C) 2016 Desktopd Developers.
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- cd "`dirname "$0"`"
- cloudflareRulesLimit=200
- configPath="./config"
- [ -f "$configPath" ] || {
- printf "No such configuration file: %s\n" "$configPath"
- exit 1
- }
- . "$configPath"
- [ "$cloudflareAuthEmail" ] && [ "$cloudflareAuthKey" ] || {
- printf "Invalid configuration file: %s\n" "$configPath"
- exit 1
- }
- dataDir="./data"
- exitListPath="${dataDir}/exit-list"
- exitListCachePath="${dataDir}/exit-list.cache"
- whitelistDBDir="${dataDir}/whitelist-db"
- version='1.0'
- faqURI='https://www.torproject.org/docs/faq-abuse.html.en'
- curlUserAgent="Mozilla/5.0 (compatible; ExitWhitelister/${version}; +${faqURI})"
- exitListURI='https://check.torproject.org/exit-addresses'
- onionooEndpointAPI='https://onionoo.torproject.org'
- cloudflareEndpointAPI='https://api.cloudflare.com/client/v4'
- mkdir -p "$dataDir"
- mkdir -p "$whitelistDBDir"
- getExitList () {
- torsocks -i curl --retry 5 -A '' "$exitListURI" \
- | grep 'ExitAddress' | awk '{print $2}' | sort -V | uniq
- }
- getExitListOnionoo () {
- torsocks -i curl -A '' --retry 5 \
- "${onionooEndpointAPI}/details" \
- -G -d running=True -d flag=Exit \
- -d fields=exit_probability,or_addresses -d order=-consensus_weight \
- -d limit="$cloudflareRulesLimit" \
- | grep '"or_addresses"' \
- | sed 's|^.*"or_addresses":\["\([^"]*\)".*$|\1| ; s|:.*||'
- }
- # Single IP address -> whitelist ID
- createWhitelistID () {
- {
- # POST
- curl \
- -A "$curlUserAgent" \
- -H "X-Auth-Email: ${cloudflareAuthEmail}" \
- -H "X-Auth-Key: ${cloudflareAuthKey}" \
- -H "Content-Type: application/json" \
- -H "Accept: application/json" \
- --data-binary '@-' \
- "${cloudflareEndpointAPI}/user/firewall/access_rules/rules" <<JSON
- {"mode":"whitelist"
- ,"notes":"Exit whitelist: automatically managed"
- ,"configuration":
- {"target":"ip"
- ,"value":"${1}"}}
- JSON
- } \
- | sed 's/,/,\n/' | grep '"id":' | sed 's/^.*"id":"\([^"]*\)".*$/\1/' \
- | head -n 1
-
- # Note: This is a quick 'n dirty attempt to JSON 'parsing'
- # TODO: It may be better to write a generic JSON parser even in shell script
- }
- # Whitelist ID
- removeWhitelistById () {
- # DELETE
- curl \
- -A "$curlUserAgent" \
- -H "X-Auth-Email: ${cloudflareAuthEmail}" \
- -H "X-Auth-Key: ${cloudflareAuthKey}" \
- -X DELETE \
- "${cloudflareEndpointAPI}/user/firewall/access_rules/rules/${1}"
- }
- # Single IP address
- addWhitelist () {
- id="`createWhitelistID "${1}"`"
- [ "$id" ] || return 1
- echo "$id" > "${whitelistDBDir}/${1}"
- }
- # Single IP address
- removeWhitelist () {
- id="`cat "${whitelistDBDir}/${1}" 2>/dev/null`"
- [ "$id" ] || return 1
- removeWhitelistById "$id" && shred -uz "${whitelistDBDir}/${1}"
- }
- getExitListOnionoo > "$exitListPath"
- [ -f "$exitListCachePath" ] || touch "$exitListCachePath"
- for obsoleteIP in `\
- diff "$exitListCachePath" "$exitListPath" \
- | grep '^<' | sed 's/^<\s*//' `
- do [ "$obsoleteIP" ] || continue
- printf "[-] Removing an IP from the whitelist:\t%s\n" "$obsoleteIP"
- removeWhitelist "$obsoleteIP" || {
- printf "\n[!] Failed while removing:\t%s\n" "$obsoleteIP"
- }
- sleep 1
- done
- for newIP in `\
- diff "$exitListCachePath" "$exitListPath" \
- | grep '^>' | sed 's/^>\s*//' `
- do [ "$newIP" ] || continue
- printf "[+] Adding a new IP to the whitelist:\t%s\n" "$newIP"
- addWhitelist "$newIP" || {
- printf "\n[!] Failed while adding:\t%s\n" "$newIP"
- }
- sleep 1
- done
- #exit
- cat "$exitListPath" > "$exitListCachePath"
- # vim: set ts=4 noet ai
|