# module-http-whitelist **Repository Path**: fifilyu/module-http-whitelist ## Basic Information - **Project Name**: module-http-whitelist - **Description**: 基于 Linux Netfilter 过滤 HTTP 协议中的 Host 字段,也就是域名白名单 - **Primary Language**: C - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 16 - **Forks**: 7 - **Created**: 2015-03-31 - **Last Updated**: 2024-05-21 ## Categories & Tags **Categories**: networklib **Tags**: None ## README # module-http-whitelist 基于 Linux Netfilter 过滤 HTTP 协议中的 Host 字段,也就是域名白名单 == 使用场景 需要一个简单的域名防火墙,只有指定的域名或者网络才能访问本机服务端口(默认 80端口)。 本机*直接提供服务* 或 *作为转发网关* 此模块均可用。 == 代替方案 使用 iptables 的 string 模块,可以实现相同的功能。白名单数量少或 HTTP 流量小时,强烈建议使用此方案。 [NOTE] 白名单数量增多或 HTTP 流量非常大时,由于 string 模块匹配是在整个包中查找字符串,匹配速度会明显下降。 === string 模块使用方法 ---- #1. 创建自定义链 # IP 白名单 iptables -N whitelist_network # HTTP 头 iptables -N http_header # 域名白名单 iptables -N whitelist_host #2. 匹配 IP 白名单匹配 # 访问 TCP 协议 80 端口的包进入 whitelist_network 链 iptables -A INPUT -p tcp --dport 80 -j whitelist_network # 放行指定网络的包,不做任何过滤 iptables -I whitelist_network -p tcp -s 8.8.8.8/24 -j ACCEPT # 包进入 http_header 链 iptables -A whitelist_network -p tcp -j http_header #3. 匹配 HTTP 包 # 匹配包内容里面的 "Host:" 字符串,并进入 whitelist_host 链 iptables -I http_header -p tcp -m string --string "Host:" --algo bm -j whitelist_host # 不是 HTTP 包,直接放行 iptables -A http_header -p tcp -j ACCEPT #4. 匹配域名白名单匹配 # 匹配 HTTP 头中 "Host: " 之后的字符串,比如 "Host: abc.com" iptables -I whitelist_host -p tcp -m string --string "abc.com" --algo bm -j ACCEPT iptables -I whitelist_host -p tcp -m string --string "www.abc.com" --algo bm -j ACCEPT iptables -I whitelist_host -p tcp -m string --string "123.456.798.test.abc.com" --algo bm -j ACCEPT iptables -I whitelist_host -p tcp -m string --string "123.com" --algo bm -j ACCEPT iptables -I whitelist_host -p tcp -m string --string ".123.com" --algo bm -j ACCEPT # 不在域名白名单中的域名,无法访问 80 端口 iptables -A whitelist_host -p tcp -j DROP ---- == 端口 默认过滤 80 端口 [NOTE] 如果 Web 服务端口为 8080,修改源代码中的 `#define HTTP_PORT 80` 为 `#define HTTP_PORT 8080` 即可。 [NOTE] 端口变化不频繁,所以没考虑写到配置文件。 == 支持内核版本 2.6.18 及以上版本 == 开发以及测试平台 * CentOS 5, 内核版本 2.6.18 * CentOS 6, 内核版本 2.6.32 * CentOS 7, 内核版本 3.10.0 * Arch Linux, 内核版本 3.19.2 == 配置文件 主机信息将会保存到 `/etc/http_whitelist` 目录下。 ==== 初始化配置文件 ---- $ sudo mkdir /etc/http_whitelist $ sudo touch /etc/http_whitelist/host /etc/http_whitelist/network ---- ==== 域名白名单 /etc/http_whitelist/host 此名单中的域名可以被任意位置的用户访问。 支持普通域名、无限子域名以及泛域名,每行一个,以回车符分割。 .格式示例 ---- abc.com www.abc.com 123.456.798.test.abc.com 123.com *.123.com ---- ==== IP 白名单 /etc/http_whitelist/network 白名单模块会忽略在此文件中的单个 IP 地址 或 属于指定网络的 IP 地址,不会过滤任何 HTTP 包。相当于透明直通(不处理数据)。 支持单 IP 以及 CIDR 风格的网络地址格式,每行一个,以回车符分割。 CIDR 说明: http://zh.wikipedia.org/zh/%E6%97%A0%E7%B1%BB%E5%88%AB%E5%9F%9F%E9%97%B4%E8%B7%AF%E7%94%B1[无类别域间路由(Classless Inter-Domain Routing、CIDR)] .格式示例 ---- 0.0.0.0/0 1.1.1.1/1 2.2.2.0/24 8.8.8.8 8.8.4.4 ---- 0.0.0.0/0 :: 相当于未使用白名单模块,不会过滤来自任何网络的 HTTP 包 [NOTE] 如果本机作为转发网关,必须添加内网网段,内网网络才能访问公网。 比如本机 IP 地址为 1.1.1.1,内网网段为 192.168.1.0/24。 将 192.168.1.0/24 写入 `/etc/http_whitelist/network` 文件,内网网络才能访问公网。 == 编译安装 === 依赖包 CentOS 5/6/7:: sudo yum install kernel-devel Arch Linux:: sudo pacman -S linux-headers === 编译 ---- $ git clone https://github.com/fifilyu/module-http-whitelist.git $ cd module-http-whitelist $ make ---- === 安装及卸载 ==== 加载模块 ---- $ sudo insmod http_whitelist.ko ---- 加载模块后,会有如下日志: ---- 3月 27 00:44:00 archlinux kernel: Loading module "http_whitelist" ---- ==== 卸载模块 ---- $ sudo rmmod http_whitelist.ko ---- 卸载模块后,会有如下日志: ---- 3月 27 01:16:15 archlinux kernel: Unloading module "http_whitelist" ---- == 测试结果说明 == IP 白名单 . 在此名单中的远程 IP 地址,访问 www.abc.com (*在 域名白名单中*),将会看到 Web 服务的响应 HTTP 内容 . 在此名单中的远程 IP 地址,访问 www.xxx.com (*不在 域名白名单中*),将会看到 Web 服务的响应 HTTP 内容 . 不在此名单中的远程 IP 地址,访问任何域名,请求都将会被转交给 域名白名单 审核 == 域名白名单 . 在 IP 白名单中的用户(远程 IP 地址)发起的 HTTP 请求,不会出现在此名单中 . 任意网络位置的用户,访问 www.abc.com (*在 域名白名单中*),将会看到 Web 服务的响应 HTTP 内容 . 任意网络位置的用户,访问 www.xxx.com (*不在 域名白名单中*),不会看到 Web 服务的响应 HTTP 内容, 只会看到浏览器提示的 “连接被重置” 字样