You are not logged in.

#1 2019-02-26 12:25:11

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

blockchina - A shellscript to block connections from China

Blockchina - A script to block all connections from China

So, this wasn't really fit for Programming & Scripting, so I'm going to post this here. This is a quick little script to, quite simply, block all incoming connections from China. It's not meant to be a racist script, but if you're running, for example, sshd, nginx, or some other server for private use, you might notice that your systemd journal is starting to fill up with logs of hundreds of connection attempts, all coming from China. This uses up a lot of bandwidth, and acts as a DOS attack until the offending client has completed some sort of dictionary attack in an attempt to gain access to files on your system.
This of course, wan't good, so I made a script that can:

- Block all incoming connections from China, and
- Update that blocklist when re-run

So, basically, it just creates an ipset set, and makes an iptables rule to drop all connections from that set. This isn't a long process, but this script automates it.

I must admit, it does have some sleeps so that the use can see what the script is doing (and to make it look cooler)

The script
#!/bin/sh
#
# Download a list of all Chinese IP-addresses, and 
# issue a full ban on them using ipset and iptables
# The script is (i believe) POSIX-compatible
# The only dependencies are a POSIX-compliant shell, GNU wget, iptables, and ipset
# NB: This script was made for Arch Linux. Please change the iptables config path and the ipset config file below
#
# Written by: Juha Kankare (bbs.archlinux.org: JuhaJGamer) 2019-02-26
#
# Please consider other options for higher configurability and/or blocking multiple countries
#

#Just a confirmation function
confirm() {
    # call with a prompt string or use a default
    printf "%s" "$1"
    read -r response
    case "$response" in
        [yY][eE][sS]|[yY])
            true
            ;;
        *)
            false
            ;;
    esac
}

#some tput checks
colorspace=$(tput colors)
errorcolor=1
codecolor=4
importantcolor=7
importantbg=1
deps="iptables ipset wget rm"
SLOW=""

case $colorspace in
    "16")
        errorcolor=9
        importantbg=9
        ;;
    "256")
        codecolor=40
        errorcolor=196
        importantbg=196
        ;;
    *)
esac

#options
while [ $# -gt 0 ]; do
    key="$1"
    case $key in
        -s|--slow) #slow mode
            SLOW="sleep 1s"
            shift
            ;;
        -h|--help) #help
            printf "Usage: blockchina.sh [options]\nOptions:\n  -s --slow\t Slow mode (aka. delays between commands, useful only for matrix-style showing off or debugging)\n  -h --help\t Show this help\n";
            exit 0
            ;;
        *)
            shift
            ;;
    esac
done

#Check user. If we're not root, cancel the script
if [ "$(id -u)" -ne $(id -u root) ]; then #If not user 0 (root) then
    tput setaf $errorcolor #set error color
    printf "ERROR: Script must be run as root\n" 1>&2
    tput sgr0
    exit 1 #Exit with code 1 (error)
fi

#Check dependencies
printf "Checking dependencies"
for dep in $deps; do
    $SLOW
    type "$dep" >/dev/null 2>&1 && continue
    printf " ... [error]\n"
    tput setaf $errorcolor
    printf "ERROR: missing dependency: %s\n" "$dep"
    tput sgr0
    exit 1
done
printf " ...................... [done]\n"

#Check for existing china set and destroy it
printf "Checking for existing china block set"
$SLOW
if ipset -L | grep -Fxq "Name: china"; then #If the set does exist
    printf " ...... [found]\n"
    printf "Deleting existing set"
    iptables -D INPUT -m set --match-set china src -j DROP 2> /dev/null >/dev/null #This is required to clear out a previous iptables rule that would block the destruction of the set
    ipset -X china #Now we can freely destroy the set

    #If the deletion didn't succeed
    if [ "$?" -ne "0" ]; then
        tput setaf $errorcolor
        printf "\nERROR: Could not delete ipset set " 1>&2
        tput setaf $codecolor
        printf "china" 1>&2
        tput setaf $errorcolor
        printf ". Try deleting it manually and/or re-running the script.\n" 1>&2 #Alert the user
        tput sgr0
        exit 1 #Die
    fi
    printf " ...................... [done]\n"
else
    printf " ...... [not found]\n" #Just more verbosity
fi

#Create china set
printf "Creating china set"
$SLOW
ipset -N china hash:net
printf " ......................... [done]\n"

#Remove any previous lists
printf "Removing /tmp/cn.zone if the file exists"
$SLOW
rm /tmp/cn.zone > /dev/null 2>&1
printf " ... [done]\n"

#Download newest list
printf "Downloading newest IP list"
$SLOW
wget -P /tmp/ http://www.ipdeny.com/ipblocks/data/countries/cn.zone >/dev/null 2>&1
printf " ................. [done]\n"

#Iterate trough all the china ips,
#And paste them onto the set
printf "Adding all the IPs into the china set"
$SLOW
for i in $(cat /tmp/cn.zone ); do ipset -A china "$i"; done
printf " ...... [done]\n" #Believe it or not, we don't need one here
#Save ipset
printf "Saving the new ipset configuration"
$SLOW
ipset save > /etc/ipset.conf
printf " ......... [done]\n"

#Check if the iptables rule already exists (this shouldn't happen as we already destroyed the rule earlier, but just as a sanity check)
printf "Checking for an iptables rule"
$SLOW
iptables -C INPUT -m set --match-set china src -j DROP > /dev/null 2> /dev/null

#If the above check returned anything but 0 (0 = found, !0 = not found)
if [ "$?" -ne "0" ]; then
    printf " .............. [not found]\n"
    confirm "Would you like to add an iptables rule? [y/N]: " && iptables -A INPUT -m set --match-set china src -j DROP
    if [ "$?" -ne "0" ]; then #If we didn't add a rule
        tput setaf $importantcolor
        tput setab $importantbg
        tput bold
        printf "IMPORTANT: "
        tput sgr0
        printf "Rule not added. The set will "
        tput setaf $errorcolor
        tput bold
        printf "NOT TAKE EFFECT"
        tput sgr0
        printf " until the rule is added. Consider adding the rule manually or re-running this script and adding it.\n" #Alert the use (again)
    else #If we did add a rule
        #Ask if we should save it
        confirm "Would you like to save the new iptables configuration? [y/N]: " && iptables-save > /etc/iptables/iptables.rules
        if [ "$?" -ne "0" ]; then #If We (again) didn't save, alert the user
            tput setaf $importantcolor
            tput setab $importantbg
            tput bold
            printf "IMPORTANT:"
            tput sgr0
            printf " The iptables configuration was not saved. This means that, after a reboot, the iptables configuration including the rule"
            tput setaf $errorcolor
            tput bold
            printf " WILL NOT TAKE EFFECT"
            tput sgr0
            printf ". Consider saving manually or re-running this script and selecting YES when asked to save.\n" #So that's the alert
        fi
    fi
else
    printf "............... [found]\n"
fi

#One last alert to notify the user
tput setaf $importantcolor
tput setab $importantbg
tput bold
printf "IMPORTANT:"
tput sgr0
printf " Even if the configuration was saved, the configuration will not take effect after a reboot unless the iptables systemd service is enabled. If it is enabled, ignore this message. If it is not, consider enabling it by running "
tput setaf $codecolor
printf "systemctl enable iptables "
tput sgr0
printf "as root.\n"

#PS
tput setaf $importantcolor
tput setab $importantbg
tput bold
printf "IMPORTANT:"
tput sgr0
printf " The china-block set will not reload after a reboot if the ipset systemd service is not enabled. If it is not, please enable it by running "
tput setaf $codecolor
printf "systemctl enable ipset "
tput sgr0
printf "as root.\n"

If you want the script hosted somewhere, tell me a good place to host it so it can be wget'd directly.

EDIT: The script is now fairly portable. I think. Tell me if anything is wrong.

Last edited by JuhaJGamer (2019-02-26 21:04:28)

Offline

#2 2019-02-26 13:00:16

ayekat
Member
Registered: 2011-01-17
Posts: 1,348
Website

Re: blockchina - A shellscript to block connections from China

JuhaJGamer wrote:
sleep 1s #the illusion of doing something (these are not actually required but the script looks cooler with these)
  • In what universe is a purposefully slowed down program considered "cool"…?

  • What shell variant do you assume here? Your script is missing a shebang, and you're using some non-portable features (like -e and -n flags to `echo`) or bashisms (like `read -p`).

  • You are using hardcoded ANSI escape codes, which may break in some cases. More offendingly, though, you are using non-standard escape codes like \033[91m.

  • The part of checking for packages being installed can be moved out to a separate function to reduce redundancy. Or even better, don't do it at all (that's the package manager's job).

if [ "$?" -ne "0"Â ]; then
…
iptables -D INPUT -m set --match-set china src -j DROP 2> /dev/null /dev/null
  • Typos?


{,META,RE}PKGBUILDSpacman-hacks (includes makemetapkg and remakepkg) │ dotfiles

Offline

#3 2019-02-26 13:20:49

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

Sorry, I not realize my script is not portable, and will re-write it as portably as I can

Offline

#4 2019-02-26 13:36:25

ayekat
Member
Registered: 2011-01-17
Posts: 1,348
Website

Re: blockchina - A shellscript to block connections from China

JuhaJGamer wrote:

Sorry, I not realize my script is not portable, and will re-write it as portably as I can

You could also just set a shebang that indicates that this is, in fact, a bash script. smile


{,META,RE}PKGBUILDSpacman-hacks (includes makemetapkg and remakepkg) │ dotfiles

Offline

#5 2019-02-26 13:37:16

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

I'm adding that too. But the ANSI codes are still a problem, as bash can be run under xterm too.

Offline

#6 2019-02-26 14:00:23

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 22,272
Website

Re: blockchina - A shellscript to block connections from China

ayekat wrote:

In what universe is a purposefully slowed down program considered "cool"…?

That was the first thing that caught me.  Your response to it was far more tactful than one I could have managed.  But to answer the rhetorical question, I think the universe inhabited by those other more popular OSs.

JuhaJGamer, there is no need for a subshell just to echo an error message - get rid of those parentheses.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#7 2019-02-26 14:09:45

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

Alright – I've done that. I have also made this sh-compatible and checked with three POSIX-compliant shells that it indeed does work. I think it's pretty much ready.

Offline

#8 2019-02-26 14:26:09

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 22,272
Website

Re: blockchina - A shellscript to block connections from China

Is the updated script somewhere?

I see also that you have a lot of code to check whether some dependencies are present (and even try to install them).  As noted above, this is not generally done, and probably shouldn't be - just list the dependencies in the script, and maybe check for them and exit with an error if they are missing.  But in either case, if you are going to do these checks, check for everything you use.  The script assumes wget is present, but it is not checked for.

A simpler and more portable approach (not relying on pacman or arch) would be something like the following:

depends='ipset iptables wget'

for dep in $depends; do
   type $dep >/dev/null 2>&1 && continue
   printf 'missing dependency %s\n' $dep
   exit 1
done

"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#9 2019-02-26 14:27:07

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

Thanks, Inspector parrot, didn't even think of that. The updated script will come in like 10-20 minutes

Last edited by JuhaJGamer (2019-02-26 14:51:49)

Offline

#10 2019-02-26 14:48:14

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

The script is now updated. Thank you everyone for the help.

Offline

#11 2019-02-26 15:16:51

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 22,272
Website

Re: blockchina - A shellscript to block connections from China

That looks great.  I personally don't have any use for it, but it much more readable, portable, and flexible now.  The "slow" still baffles me, but people's tastes differ - so having it as an option seems like a good idea to provide it for those who'd like it.  But you could do without the 'slow' function.  Set SLOW="" as a default, then SLOW="sleep 1s" if the option is provided.  Then when you want to use it, just put "$SLOW" on the line.  A set but empty variable will expand to nothing and controll flow will pass right through it without error.

Last edited by Trilby (2019-02-26 15:18:34)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#12 2019-02-26 15:18:19

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

Well, it just looks like it's working harder and I personally would like to catch what it's doing before it does it. It's also optional now, so it shouldn't be a problem.

Offline

#13 2019-02-26 16:19:39

amish
Member
Registered: 2014-05-10
Posts: 414

Re: blockchina - A shellscript to block connections from China

If you are using nftables then see:
https://aur.archlinux.org/packages/nftables-geoip-db/

README file: https://aur.archlinux.org/cgit/aur.git/ … s-geoip-db


If you are using iptables (xtables) then see:
https://aur.archlinux.org/packages/xtables-geoip-db/
It needs: https://aur.archlinux.org/packages/xtables-addons-dkms/


Using any of above you can block any country based on Maxmind's database.

I used xtables earlier but now I have switched to nftables.

nftable package does not require any additional kernel module. It just provides nftables compatible sets which you can include in your nftables.conf as given in README file.

Skeleton code: (after installing the package)

include "/usr/share/nft_geoip/CN.ipv4"
add set ip filter geo_CN { type ipv4_addr; flags interval; elements = $geoip4_iso_country_CN }
add rule ip filter INPUT ct state new tcp dport ssh ip saddr @geo_CN drop

Last edited by amish (2019-02-26 16:31:43)


Forum signature: I discuss. I put my thoughts strongly. But I definitely respect all developers and time they put in.

Offline

#14 2019-02-26 16:23:28

JuhaJGamer
Member
Registered: 2019-02-26
Posts: 8

Re: blockchina - A shellscript to block connections from China

amish wrote:

If you are using nftables then see:
https://aur.archlinux.org/packages/nftables-geoip-db/

README file: https://aur.archlinux.org/cgit/aur.git/ … s-geoip-db


If you are using iptables (xtables) then see:
https://aur.archlinux.org/packages/xtables-geoip-db/
It needs: https://aur.archlinux.org/packages/xtables-addons-dkms/


With all of above you can block any country based on Maxmind's database. (not just china)

I used xtables earlier but now I have switched to nftables.

nftable package does not require any additional kernel module. It just provides nftables compatible sets which you can include in your nftables.conf as given in README file.

Seems useful, but a slight bit more complicated than just using this script. Of course, this is way more configurable. This script can also block any country, just have to change cn.zone to, for example, us.zone (to block all US connections).

Offline

#15 2019-03-01 17:23:10

mkschu
Member
Registered: 2017-04-30
Posts: 1

Re: blockchina - A shellscript to block connections from China

Thanks for sharing the script, JuhaJGamer. I've been noticing this too, and today's Linux Journal news brief includes an entry "New Crypto-mining Group Targeting Linux Servers." This seems to match what I am seeing on my servers, with nginx recording hundreds of failed GETs trying to access MySQL, PHPMyAdmin, and WP-admin (none of which I'm running) all coming from China-based IPs. The full article which LJ links to, with lots of detail on the attack mechanism, is at: https://www.intezer.com/blog-technical- … cha-group/.

Offline

Board footer

Powered by FluxBB