一、IP 基础知识
以下 IP 是基于 IPv4
IP 地址格式如 192.168.110.168/24,这也叫斜线记法。
以下从两个角度理解斜线记法。
1.1 从人的角度理解斜线记法

例如 192.168.1.0/24 表示 32 位的二进制地址中(任何 IP 的二进制地址都是 32 位),前 24 位为网络前缀,后 8 位代表主机号。
在换算中,192.168.1.0/24 对应的二进制为:
1
| 1100 0000,1010 1000,0000 0001,0000 0000
|
其中后 8 位为主机号,总共有 8 位。
当这 8 位全为 0 时,取最小地址 192.168.1.0,
当这 8 位全为 1 时,取最大地址 192.168.1.255。
但请注意,在实际中,主机号全为 0 或者全为 1 的地址一般不使用,作为预留地址另有作用。
所以,第一个地址为:1100 0000,1010 1000,0000 0001,0000 0001
即 192.168.1.1
最后一个地址为:1100 0000,1010 1000,0000 0001,1111 1110
即 192.168.1.254。
因此,192.168.1.0/24 代表的 IP 段就是 192.168.1.1 至 192.168.1.254。也可以说这些 IP 在同一个子网中。
1.2 从机器的角度理解斜线记法
斜线记法是给人看的,其实对机器来说,是没有斜线记法的。
因此,为了将斜线记法,变成让机器可理解的,就引入了 子网掩码(地址掩码) 的概念。
斜线后面的数字就是子网掩码中 1 的个数 (从高位到低位),比如 /20 表示的子网掩码就是
1
| 1111 1111, 1111 1111, 1111 0000, 0000 0000
|
比如 IP 192.168.110.199
,子网掩码 255.255.255.0
,用计算机能理解的表示
- IP地址
1100 0000, 1010 1000, 0110 1110, 1100 0111
- 子网掩码地址
1111 1111, 1111 1111, 1111 1111, 0000 0000
将 IP 地址与子网掩码地址,进行 AND 运算,即可得到子网地址。
1
| 1100 0000, 1010 1000, 0110 1110, 0000 0000
|
也就是 IP 地址 192.168.110.199/24 所在的子网地址是 192.168.110.0/24

1.3 代码计算网络地址的 IP 范围
执行以下代码编译、运行
1 2
| javac -encoding utf-8 IPCalcFreedom.java java -Dfile.encoding=utf-8 IPCalcFreedom
|

源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| import java.util.Scanner;
public class IPCalcFreedom { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.printf("输入 IP 地址:"); String ipAddress = scanner.nextLine(); resolveIP(ipAddress); }
public static void resolveIP(String ipAddress) { String[] split = ipAddress.split("[./]"); System.out.printf("%s 表示前 %s 位为网络号, 后 %s 位为主机号 \n", ipAddress, split[4], (32 - Integer.parseInt(split[4]))); StringBuilder sb = new StringBuilder(); for (int i = 0; i < split.length - 1; i++) { sb.append(complement(Integer.toBinaryString(Integer.parseInt(split[i])))); } int netIndex = Integer.parseInt(split[4]); String ipBinary = sb.toString(); String netBinary = ipBinary.substring(0, netIndex); String hostBinary = ipBinary.substring(netIndex); System.out.printf("网络号二进制为 %s\n", netBinary); String maxHostBinary = getHostBinary(hostBinary, true); String minHostBinary = getHostBinary(hostBinary, false); System.out.printf("主机号二进制极值排除全为 0 或者全为 1, 用于预留地址. 最小值为 %s, 最大值为 %s\n", minHostBinary, maxHostBinary); String minIPBinary = netBinary + minHostBinary; String maxIPBinary = netBinary + maxHostBinary; String minIPDecimal = ipBinaryToDotDecimal(minIPBinary); String maxIPDecimal = ipBinaryToDotDecimal(maxIPBinary); System.out.printf("IP 地址 %s 表示的范围是 %s-%s\n", ipAddress, minIPDecimal, maxIPDecimal); }
public static String ipBinaryToDotDecimal(String binary) { String[] strArray = new String[4]; for (int i = 0; i < 4; i++) { int startIndex = i * 8; int endIndex = startIndex + 8; strArray[i] = String.valueOf(Integer.parseInt(binary.substring(startIndex, endIndex), 2)); } return String.join(".", strArray); }
public static String getHostBinary(String binary, boolean max) { String target, replace; if (max) { target = "1"; replace = "0"; } else { target = "0"; replace = "1"; } String external = binary.replaceAll("[01]", target); return external.substring(0, external.length() - 1) + replace; }
public static String complement(String ipBinary) { int length = ipBinary.length(); if (length == 8) { return ipBinary; } else { return String.format("%8s", ipBinary).replace('','0'); } } }
|
二、防火墙配置
2.1 管理
防火墙状态管理
1 2 3 4 5 6
| systemctl start firewalld
systemctl stop firewalld
systemctl restart firewalld
|
防火墙自启动管理
1 2 3 4
| systemctl enable firewalld
systemctl disable firewalld
|
2.2 查询规则
查看配置的所有的规则
1 2 3
|
firewall-cmd --list-all
|
其他简单查看命令
1 2 3 4 5 6
| firewall-cmd --list-ports
firewall-cmd --list-services
firewall-cmd --list-protocols
|

2.3 单一配置
2.3.1 协议配置
1 2 3 4
| firewall-cmd --zone=public --add-protocol=tcp --permanent && firewall-cmd --reload
firewall-cmd --zone=public --remove-protocol=tcp --permanent && firewall-cmd --reload
|
2.3.2 端口配置
1 2 3 4
| firewall-cmd --zone=public --add-port=9999/tcp --permanent && firewall-cmd --reload
firewall-cmd --zone=public --remove-port=9999/tcp --permanent && firewall-cmd --reload
|
2.4 自定义配置
2.4.2 配置自由放行规则
1 2 3 4 5
| firewall-cmd --permanent --add-rich-rule='rule family="ipv4"source address="10.0.0.0/24"port protocol="tcp"port="9999"accept' && firewall-cmd --reload
firewall-cmd --permanent --add-rich-rule='rule family="ipv4"source address="10.0.0.0/24"port protocol="tcp"port="9999"accept' && firewall-cmd --reload
|
2.4.3 配置自由禁止规则
1 2 3 4 5
| firewall-cmd --permanent --add-rich-rule='rule family="ipv4"source address="10.0.0.0/24"port protocol="tcp"port="9999"drop' && firewall-cmd --reload
firewall-cmd --permanent --remove-rich-rule='rule family="ipv4"source address="10.0.0.0/24"port protocol="tcp"port="9999"drop' && firewall-cmd --reload
|
三、端口转发
将本机 80 的请求转发到指定机器的 9999 端口
1 2 3 4
| firewall-cmd --add-forward-port=port=80:proto=tcp:toport=9999:toaddr=10.0.0.10 --zone=public --permanent
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=9999:toaddr=10.0.0.10 --zone=public --permanent
|
四、参考致谢
浅谈 linux 系统 firewalld 防火墙常用策略(ipv6、ipv4)_firewall-cmd ipv6_cs 阿坤 dn 的博客 -CSDN 博客
Linux 服务器 Firewalld 防火墙配置端口转发 _51CTO 博客 _linux 防火墙设置 firewalld
通俗易懂解释 IP 段 192.168.1.0/24 和 192.168.0.0/16_ 运维 _PHP 面试网
firewall-cmd 命令,Linux firewall-cmd 命令详解:Linux 上新用的防火墙软件,跟 iptables 差不多的工具 - Linux 命令搜索引擎
192.168.0.1/27 表示什么 _molaifeng 的博客 -CSDN 博客 _/27