What's new

Block specific ip using iptables

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Keith Hong

New Around Here
Calling all master network...

I tried to use my AsusWRT-Merlin Router iptable features to block specific static ip range from accessing destination ip other than specified. Others, free for all.

My gateway is 192.168.1.1

I tried to set my static ip lan range from 192.168.1.2 - 192.168.1.20 go through firewall.

but 192.168.1.21 - 192.168.1.155 free from firewall.

firewall ip range only allow to access google.com (172.217.24.238).

any idea how to setup my iptables?
 
Try using Firewall > Network Services Filter
That doesn't work as I wish.

I wonder if this works..


iptables --policy INPUT DROP
iptables --policy OUTPUT DROP
iptables --policy FORWARD DROP
iptables -A INPUT -s 192.168.1.0/20 -d 172.217.24.238 -j ACCEPT #access to google
iptables -A INPUT -s 192.168.1.0/20 -d 216.58.196.69 -j ACCEPT # access to gmail
iptables -A INPUT -s 192.168.1.0/20 -d 202.76.1.12 -j ACCEPT # access to server
iptables -A INPUT -s 192.168.1.21/155 -j ACCEPT # no limit to firewall
 
That doesn't work as I wish.

I wonder if this works..


iptables --policy INPUT DROP
iptables --policy OUTPUT DROP
iptables --policy FORWARD DROP
iptables -A INPUT -s 192.168.1.0/20 -d 172.217.24.238 -j ACCEPT #access to google
iptables -A INPUT -s 192.168.1.0/20 -d 216.58.196.69 -j ACCEPT # access to gmail
iptables -A INPUT -s 192.168.1.0/20 -d 202.76.1.12 -j ACCEPT # access to server
iptables -A INPUT -s 192.168.1.21/155 -j ACCEPT # no limit to firewall

No

You should learn how to specify subnet ranges using CIDR notation,

i.e.
Code:
iptables -A INPUT -s 192.168.1.21/155 -j ACCEPT # no limit to firewall
.21/155 does NOT mean addresses .21 through .155 inclusive

Also on the Router the FORWARD chain is used for LAN clients

You can create IPSETs to reduce the number of firewall rules from 23 to 4
Code:
# CIDR, 192.168.1.2-192.168.1.20

   ipset create Group1 hash:net
 
   ipset add Group1 192.168.1.2/31
   ipset add Group1 192.168.1.4/30
   ipset add Group1 192.168.1.8/29
   ipset add Group1 192.168.1.16/30
   ipset add Group1 192.168.1.20
 

# CIDR, 192.168.1.21-192.168.1.155:

   ipset create Group2 hash:net
 
   ipset add Group2 192.168.1.21
   ipset add Group2 192.168.1.22/31
   ipset add Group2 192.168.1.24/29
   ipset add Group2 192.168.1.32/27
   ipset add Group2 192.168.1.64/26
   ipset add Group2 192.168.1.128/28
   ipset add Group2 192.168.1.144/29
   ipset add Group2 192.168.1.152/30

# Now add the Firewall rules using the IPSETs

   iptables -I FORWARD -m set --match-set Group1 src -d 172.217.24.238,216.58.196.69,202.76.1.12 -j ACCEPT
   iptables -I FORWARD -m set --match-set Group2 src                                             -j ACCEPT

or create the 23 individual rules in CIDR format vs the >190??? individual rules
Code:
   iptables -I FORWARD -s 192.168.1.2/31   -d 172.217.24.238 -j ACCEPT
   iptables -I FORWARD -s 192.168.1.4/30   -d 172.217.24.238 -j ACCEPT
   iptables -I FORWARD -s 192.168.1.8/29   -d 172.217.24.238 -j ACCEPT
   iptables -I FORWARD -s 192.168.1.16/30  -d 172.217.24.238 -j ACCEPT
   iptables -I FORWARD -s 192.168.1.20     -d 172.217.24.238 -j ACCEPT
 
   iptables -I FORWARD -s 192.168.1.2/31   -d 216.58.196.69  -j ACCEPT
   iptables -I FORWARD -s 192.168.1.4/30   -d 216.58.196.69  -j ACCEPT
   iptables -I FORWARD -s 192.168.1.8/29   -d 216.58.196.69  -j ACCEPT
   iptables -I FORWARD -s 192.168.1.16/30  -d 216.58.196.69  -j ACCEPT
   iptables -I FORWARD -s 192.168.1.20     -d 216.58.196.69  -j ACCEPT
 
   iptables -I FORWARD -s 192.168.1.2/31   -d 202.76.1.12    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.4/30   -d 202.76.1.12    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.8/29   -d 202.76.1.12    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.16/30  -d 202.76.1.12    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.20     -d 202.76.1.12    -j ACCEPT
 
   iptables -I FORWARD -s 192.168.1.21                       -j ACCEPT
   iptables -I FORWARD -s 192.168.1.22/31                    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.24/29                    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.32/27                    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.64/26                    -j ACCEPT
   iptables -I FORWARD -s 192.168.1.128/28                   -j ACCEPT
   iptables -I FORWARD -s 192.168.1.144/29                   -j ACCEPT
   iptables -I FORWARD -s 192.168.1.152/30                   -j ACCEPT

NOTE: Google and GMail have multiple IP addresses/subnets!
 
Last edited:
You should learn how to specify subnet ranges using CIDR notation
This tool converts IPv4 range to CIDR. Now you don't need an Internet connection to convert an IP range to CIDR. I was cleaning the cutting room floor. Example:

Example
Code:
# range2cidr.sh 0.0.0.1 255.255.255.255
0.0.0.1/32
0.0.0.2/31
0.0.0.4/30
0.0.0.8/29
0.0.0.16/28
0.0.0.32/27
0.0.0.64/26
0.0.0.128/25
0.0.1.0/24
0.0.2.0/23
0.0.4.0/22
0.0.8.0/21
0.0.16.0/20
0.0.32.0/19
0.0.64.0/18
0.0.128.0/17
0.1.0.0/16
0.2.0.0/15
0.4.0.0/14
0.8.0.0/13
0.16.0.0/12
0.32.0.0/11
0.64.0.0/10
0.128.0.0/9
1.0.0.0/8
2.0.0.0/7
4.0.0.0/6
8.0.0.0/5
16.0.0.0/4
32.0.0.0/3
64.0.0.0/2
128.0.0.0/1


/jffs/scripts/range2cidr.sh
Code:
#!/bin/sh
#######################################################################
#
#  This tool converts IPv4 range to CIDR.
#
#  Usage:
#    range2cidr.sh {from-ip} {to-ip}
#
#  Ported from C source code published here:
#    IP Range To Cidr Convertor C Code
#    https://dzone.com/articles/ip-range-cidr-convertor-c-code
#
#######################################################################

# converts a 32-bit number to a binary string of 1's and 0's
num2bin() {
  awk '
  BEGIN {
    n = ARGV[1];
    bits = 32;
    bin = "";
    while (bits-- > 0) {
      bin = (n % 2 == 1 ? "1" : "0") bin;
      n = int(n / 2);
    }
    print bin;
  }
  ' $@
}

# converts a 32-bit number to an IPv4 address string
num2ip() {
  awk '
  BEGIN {
    n = ARGV[1];
    ip = "";
    for (i = 1; i <= 4; i++) {
      m = n % 256;
      n = int(n / 256);
      ip = (ip == "") ? m : m "." ip;
    }
    print ip;
  }
  ' $@
}

# converts an IPv4 address string to a 32-bit number
ip2num() {
  awk '
  BEGIN {
    ip = ARGV[1];
    num = 0;
    len = split(ip, array, ".");
    for (i = 1; i <= len; i++) {
      num *= 256;
      num += array[i];
    }
    print num;
  }
  ' $@
}

# makes all bits on the right side zero
makeRightSideZero() {
  awk '
  BEGIN {
    n = ARGV[1];
    b = ARGV[2];
    shift = 2 ** (b + 1);
    print int(n / shift) * shift;
  }
  ' $@
}

# makes a new IP address for range To
makeRangeTo() {
  awk 'BEGIN {print or(ARGV[1], 2 ** ARGV[2] - 1)}' $@
}

# makes a new IP address for range From
makeRangeFrom() {
  awk 'BEGIN {print or(ARGV[1], 2 ** ARGV[2])}' $@
}

MAX_CIDR_MASK=32
range2cidr() {
  local from=$1
  local to=$2
  local fromIp="$(num2bin $from)"
  local toIp="$(num2bin $to)"
  local newfrom=0
  local cidrStart=0
  let local cidrEnd=MAX_CIDR_MASK-1

  if [ $from -lt $to ]; then

    # Compare the from and to address ranges to get the first
    # point of difference
    while [ "${fromIp:$cidrStart:1}" == "${toIp:$cidrStart:1}" ]; do
      let local cidrStart++
    done
    let local cidrStart=32-cidrStart-1

    # Starting from the found point of difference make all bits on the
    # right side zero
    local newfrom=$(makeRightSideZero $from $cidrStart)

    # Starting from the end iterate reverse direction to find
    # cidrEnd
    while [ "${fromIp:$cidrEnd:1}" == "0" ] && [ "${toIp:$cidrEnd:1}" == "1" ]; do
      let local cidrEnd--
    done
    let local cidrEnd=MAX_CIDR_MASK-1-cidrEnd

    if [ $cidrEnd -le $cidrStart ]; then

      # Make all the bit-shifted bits equal to 1, for iteration #1
      range2cidr $from $(makeRangeTo $newfrom $cidrStart)
      range2cidr $(makeRangeFrom $newfrom $cidrStart) $to

    else
      echo "$(num2ip $newfrom)/$((MAX_CIDR_MASK - cidrEnd))"
    fi

  else
    echo "$(num2ip $from)/$MAX_CIDR_MASK"
  fi
}

if [ $# -ne 2 ]; then
  echo
  echo "Convert IPv4 range to CIDR"
  echo
  echo "Usage: range2cidr.sh {from-ip} {to-ip}"
  echo
else
  addrFrom=$(ip2num "$1")
  addrTo=$(ip2num "$2")
  range2cidr $addrFrom $addrTo
fi
 
Last edited:

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top