惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
P
Proofpoint News Feed
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
罗磊的独立博客
J
Java Code Geeks
月光博客
月光博客
F
Full Disclosure
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
U
Unit 42
WordPress大学
WordPress大学
A
About on SuperTechFans
C
Cyber Attacks, Cyber Crime and Cyber Security
SecWiki News
SecWiki News
Security Latest
Security Latest
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
小众软件
小众软件
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
V
Visual Studio Blog
博客园_首页
NISL@THU
NISL@THU
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Latest news
Latest news
Project Zero
Project Zero
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
博客园 - 【当耐特】
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 读:AI Agent 生产化——一份从原型到上线的速查清单 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
在Linux上限制儿童使用电脑 - 暗无天日
2026-04-14 · via 暗无天日

作为家长,你可能希望控制孩子使用电脑的时间——比如只能在晚上 6 点到 8 点登录,每天最多用 2 小时,超时后自动踢出。Windows 有专门的家长控制面板,而 Linux 虽然没有这样的集成工具,但它提供的原生机制完全可以实现同样的效果,而且更加灵活。

本文将介绍如何用纯 Linux 原生方案(PAM、cron、iptables 等)实现以下功能:

  • 限制允许登录的时间段
  • 限制每日累计使用时长
  • 超时警告并自动踢出
  • 限制可访问的网站
  • 限制可运行的程序

本文假设系统中已创建一个名为 geo 的受限用户。所有配置需要 root 权限。

限制允许登录的时间段

Linux 中控制用户登录时间的机制是 PAM(Pluggable Authentication Modules,可插拔认证模块)中的 pam_time 模块。

快速配置

首先,在 PAM 配置文件中启用 pam_time.so 。需要修改的文件取决于你使用的登录方式:

  • 控制台登录: /etc/pam.d/login
  • 图形界面登录: /etc/pam.d/lightdm/etc/pam.d/gdm
  • SSH 登录: /etc/pam.d/sshd

在上述文件的 account 部分添加一行:

account required pam_time.so

然后在 /etc/security/time.conf 中添加规则。该文件的格式为:

services;ttys;users;times

各字段含义:

services
服务名, * 表示所有服务
ttys
终端类型, * 表示所有终端
users
用户名
times
时间规则

时间规则的语法比较特别:

  • Wk 表示工作日(周一到周五), Wd 表示周末(周六、周日), Al 表示每天
  • 时间格式为 HHMM-HHMM
  • 前面加 ! 表示取反("除此时段外禁止")

例如,限制 geo 用户只能在每天 18:00 到 20:00 登录:

*;*;geo;Al1800-2000

这行规则的意思是:对所有服务、所有终端、geo 用户,允许每天 18:00-20:00 登录( Al 表示每天都适用)。注意, pam_time 的逻辑是:匹配到的允许登录,未匹配到则拒绝。

验证配置:在非允许时段尝试用 geo 账户登录,应该会看到类似 "Permission denied" 的提示。

原理说明

PAM 是 Linux 的可插拔认证框架,它将认证逻辑从应用程序中解耦出来。PAM 定义了四种模块类型:

auth
验证用户身份(如检查密码)
account
检查账户是否允许访问(如检查账户是否过期、是否在允许的时间段内)
password
管理密码更新
session
管理会话的创建和销毁

pam_time 属于 account 类型。它的工作时机是在用户通过了 auth 阶段的密码验证之后、系统创建会话之前。此时 pam_time 会检查当前时间是否匹配 time.conf 中的规则,如果不匹配则拒绝登录。

限制每日累计使用时长

pam_time 只能控制"什么时候能登录",但无法控制"登录后能用多久"。要实现每日使用时长的累计限制,需要自己动手:记录每次登录和登出的时间,然后定期检查是否超限。

快速配置

整个方案由两部分组成:一个记录登录/登出时间的脚本,和一个定期检查累计时长的脚本。

第一步:记录登录/登出时间

创建 /usr/local/bin/session-logger.sh

bash
LOGFILE="/var/log/user-sessions.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
USERNAME="$PAM_USER"
TYPE="$PAM_TYPE"

if [ -z "$USERNAME" ]; then
    exit 0
fi

case "$TYPE" in
    open_session)
        echo "LOGIN $TIMESTAMP $USERNAME" >> "$LOGFILE"
        ;;
    close_session)
        echo "LOGOUT $TIMESTAMP $USERNAME" >> "$LOGFILE"
        ;;
esac

exit 0

然后赋予执行权限:

sudo chmod +x /usr/local/bin/session-logger.sh
sudo touch /var/log/user-sessions.log
sudo chmod 600 /var/log/user-sessions.log

在 PAM 配置文件(如 /etc/pam.d/login/etc/pam.d/lightdm )的 session 部分添加:

session optional pam_exec.so /usr/local/bin/session-logger.sh

第二步:检查累计时长

创建 /usr/local/bin/check-usage.sh

bash
LOGFILE="/var/log/user-sessions.log"
TODAY=$(date '+%Y-%m-%d')
MAX_MINUTES=120  TARGET_USER="geo"
LOCKFILE="/var/run/check-usage.lock"

exec 9>"$LOCKFILE"
flock -n 9 || exit 0

calculate_usage() {
    local user=$1
    local total_seconds=0
    local login_time=""

    while IFS= read -r line; do
        local action=$(echo "$line" | awk '{print $1}')
        local timestamp=$(echo "$line" | awk '{print $2, $3}')
        local username=$(echo "$line" | awk '{print $4}')

        [ "$username" != "$user" ] && continue

        case "$action" in
            LOGIN)
                login_time="$timestamp"
                ;;
            LOGOUT)
                if [ -n "$login_time" ]; then
                    local login_ts=$(date -d "$login_time" '+%s')
                    local logout_ts=$(date -d "$timestamp" '+%s')
                    total_seconds=$((total_seconds + logout_ts - login_ts))
                    login_time=""
                fi
                ;;
        esac
    done < <(grep "$TODAY" "$LOGFILE" | grep -E "^(LOGIN|LOGOUT)")

        if [ -n "$login_time" ]; then
        local login_ts=$(date -d "$login_time" '+%s')
        local now_ts=$(date '+%s')
        total_seconds=$((total_seconds + now_ts - login_ts))
    fi

    echo $((total_seconds / 60))
}

usage=$(calculate_usage "$TARGET_USER")
remaining=$((MAX_MINUTES - usage))

if [ "$remaining" -le 0 ]; then
    echo "使用时间已到,系统将在 2 分钟后将 $TARGET_USER 踢出!" | wall 2>/dev/null
    sleep 120
    pkill -u "$TARGET_USER"
    sleep 10
    pkill -9 -u "$TARGET_USER"
elif [ "$remaining" -le 5 ]; then
    echo "$TARGET_USER 还有 $remaining 分钟的使用时间" | wall 2>/dev/null
fi

赋予执行权限,并创建 systemd timer 每分钟运行一次:

sudo chmod +x /usr/local/bin/check-usage.sh

创建 systemd service 文件:

[Unit]
Description=Check user daily usage time

[Service]
Type=oneshot
ExecStart=/usr/local/bin/check-usage.sh

创建对应的 timer 文件:

[Unit]
Description=Run check-usage every minute

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=true

[Install]
WantedBy=timers.target

启用 timer:

sudo systemctl daemon-reload
sudo systemctl enable --now check-usage.timer

原理说明

这里用到了两个机制:

PAM session 管理
当用户登录成功后,PAM 会依次调用 session 类型的模块的 open 钩子;当用户登出时,调用 close 钩子。 pam_exec.so 会将钩子类型通过环境变量 PAM_TYPE (值为 openclose )传递给外部脚本,同时通过 PAM_USER 传递用户名。
systemd timer 定时任务
OnCalendar=*-*-* *:*:00 表示每分钟整点执行一次。systemd timer 是 cron 的现代替代方案,几乎所有使用 systemd 的 Linux 发行版都内置支持。它的优势包括:自动记录日志、支持依赖关系、失败后可自动重试。这个频率足够及时地检测到超时,同时不会给系统带来明显负担。

超时警告并踢出

上一节的脚本已经包含了基本的警告和踢出逻辑。这里再详细说明一下各个踢出手段的区别。

多级警告策略

实际使用中,建议采用多级警告,给孩子一个心理准备的过程:

以下是一个示例,展示如何替换脚本中的警告逻辑:

usage=$(calculate_usage "$TARGET_USER")
remaining=$((MAX_MINUTES - usage))

if [ "$remaining" -le 0 ]; then
        echo "$TARGET_USER,今日使用时间已到!" | wall 2>/dev/null
    sleep 120
    pkill -u "$TARGET_USER"
elif [ "$remaining" -le 2 ]; then
        echo "$TARGET_USER,还有 $remaining 分钟,请保存工作!" | wall 2>/dev/null
elif [ "$remaining" -le 5 ]; then
        echo "$TARGET_USER,还有 $remaining 分钟的使用时间" | wall 2>/dev/null
fi

踢出用户的不同方式

pkill -u geo
向 geo 用户的所有进程发送 SIGTERM 信号。这是最简单的方式,但如果有进程忽略了 SIGTERM,可能无法完全清理。可以追加 pkill -9 -u geo 来强制结束。
loginctl terminate-session SESSION_ID
通过 systemd-logind 来终止指定的登录会话。这比 pkill 更精确,因为它能正确地清理会话资源。查看当前会话列表可以用 loginctl list-sessions
shutdown -h +2
2 分钟后关闭整个系统。这是最彻底的方式,但会影响所有用户。如果电脑是孩子独占使用的,这也是个不错的选择。

原理说明

wall 命令的工作原理是向系统中所有终端设备( /dev/pts/*/dev/tty* )写入消息。只有拥有终端的登录用户才能看到消息。

pkill 通过匹配进程的 UID 来选择目标进程,先发送 SIGTERM(信号 15),允许进程优雅退出。如果进程不响应,可以发送 SIGKILL(信号 9)强制终止。

loginctl 是 systemd-logind 的命令行接口。logind 作为 systemd 的用户登录管理器,跟踪系统中所有的登录会话(包括图形和终端会话)。 terminate-session 会向会话中的所有进程发送终止信号,并清理会话资源。

限制可访问网站

在 HTTPS 普及的今天,我们无法在不安装额外证书的情况下检查 HTTP 请求的内容。因此 Linux 原生方案只能在 IP 和域名级别进行过滤。下面介绍两种方法。

方法一:DNS 级过滤

通过配置本地 DNS 服务器 dnsmasq ,将不希望访问的域名解析到无效地址。

首先安装 dnsmasq

sudo pacman -S dnsmasq  

创建黑名单文件 /etc/blocked-hosts

# /etc/blocked-hosts
# 每行一个要屏蔽的域名(标准 hosts 格式)
127.0.0.1 example-bad-site.com
127.0.0.1 another-bad-site.com

/etc/dnsmasq.conf 中添加配置:

addn-hosts=/etc/blocked-hosts

然后启动 dnsmasq 并将系统 DNS 指向本地:

sudo systemctl enable --now dnsmasq
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf

这种方法的缺点是:只要孩子知道如何修改 DNS 设置,就能轻松绕过。

方法二:iptables 按用户限制

iptablesowner 模块可以根据进程的 UID 来匹配网络流量, time 模块可以按时间段匹配。两者结合,可以限制特定用户在特定时间段内的网络访问。

sudo iptables -A OUTPUT -m owner --uid-owner geo -m time --timestart 18:00 --timestop 20:00 -j ACCEPT

sudo iptables -A OUTPUT -m owner --uid-owner geo -j DROP

注意: --timestop 20:00 实际上不包含 20:00 整点,规则有效时间为 18:00:00 到 19:59:59。如果需要包含 20:00 整点,可以设置为 =--timestop 20:01=。

要持久化这些规则,可以将它们写入一个规则文件,然后在启动时自动恢复:

*filter
:OUTPUT ACCEPT [0:0]
-A OUTPUT -m owner --uid-owner geo -m time --timestart 18:00 --timestop 20:00 -j ACCEPT
-A OUTPUT -m owner --uid-owner geo -j DROP
COMMIT

恢复规则:

sudo iptables-restore < /etc/iptables/parental-control.rules

原理说明

Linux 的网络过滤由 Netfilter 框架实现。Netfilter 在网络协议栈中设置了五个钩子点:

PREROUTING
数据包进入路由之前
INPUT
数据包发往本机进程之前
FORWARD
数据包转发到其他接口之前
OUTPUT
本机进程发出的数据包
POSTROUTING
数据包发出之前

我们使用的是 OUTPUT 链,它处理本机进程发出的所有数据包。 owner 模块通过检查数据包对应的 socket 的 UID 来匹配, time 模块通过系统时间来匹配。规则从上到下依次匹配,匹配到后就执行指定的动作( ACCEPTDROP )。

限制可运行程序

不想让孩子玩某些游戏或使用某些软件?最直接的方法是通过 Linux 的权限系统来限制。

方法一:文件权限控制

Linux 的每个文件都有三组权限:所有者(owner)、所属组(group)、其他人(others)。我们可以利用这个机制来限制特定用户执行特定程序。

假设要禁止 geo 用户运行 steam

sudo groupadd restricted

sudo chgrp restricted /usr/bin/steam
sudo chmod 750 /usr/bin/steam

sudo gpasswd -d geo restricted 2>/dev/null || true

这样,只有 root 用户和 restricted 组的成员可以运行 steam ,而 geo 用户会得到 "Permission denied" 的错误。

对于需要限制的每个程序,重复上述步骤即可。也可以写一个脚本来批量处理:

bash
PROGRAMS="/usr/bin/steam /usr/bin/wine /usr/bin/discord"

for prog in $PROGRAMS; do
    if [ -f "$prog" ]; then
        sudo chgrp restricted "$prog"
        sudo chmod 750 "$prog"
        echo "Restricted: $prog"
    fi
done

需要注意:当软件包更新时,权限可能会被重置。可以将这个脚本放在 systemd 的 timer 或 pacman 的 hook 中定期执行。

方法二:AppArmor

AppArmor 提供了更强大的强制访问控制(MAC)。与文件权限不同,AppArmor 的策略无法被用户(包括文件所有者)修改。

在 Arch Linux 上安装并启用 AppArmor:

sudo pacman -S apparmor
sudo systemctl enable --now apparmor

AppArmor 通过 profile 来定义程序的访问权限。需要注意的是,AppArmor 的 profile 是绑定到程序的,不能直接按用户限制。要实现按用户限制,需要配合 pam_apparmor 模块,在用户登录时为不同用户加载不同的 profile。

首先,创建一个限制性的 profile:

# /etc/apparmor.d/restrict-geo-steam
abi <abi/4.0>,
include <tunables/global>

/usr/bin/steam {
    include <abstractions/base>

    # 只允许特定用户组执行
    # 注意:AppArmor 本身不直接支持按用户过滤,
    # owner 关键字匹配进程所有者(即运行 steam 的用户)
    owner /usr/bin/steam rx,
}

如果需要更精确的按用户控制,建议结合文件权限方法使用——将程序的组设为受限组,然后在 AppArmor profile 中限制该组的访问。或者使用 pam_apparmor 在用户登录时动态加载不同的 profile。

加载 profile:

sudo apparmor_parser -r /etc/apparmor.d/restrict-geo-steam

原理说明

DAC(自主访问控制)
Linux 默认的权限模型。每个文件有三组权限位(读 r、写 w、执行 x),分别对应所有者、所属组、其他人。文件的所有者可以自主修改文件的权限。"自主"的含义就在于此——权限由所有者决定。
MAC(强制访问控制)
AppArmor 实现的权限模型。策略由系统管理员定义,普通用户无法绕过或修改。AppArmor 使用基于路径的匹配(而非 SELinux 的基于标签的匹配),配置相对简单。

总结

本文介绍了五种用纯 Linux 原生机制限制儿童使用电脑的方法:

限制登录时段
使用 PAM 的 pam_time 模块,通过 /etc/security/time.conf 配置
限制使用时长
使用 pam_exec 记录登录/登出时间,配合 cron 定时检查
超时踢出
使用 wall 发送警告, pkillloginctl 踢出用户
限制网站访问
使用 dnsmasq 做 DNS 过滤,或 iptables 按用户和时间限制网络访问
限制可运行程序
使用文件权限或 AppArmor 控制程序执行

这些方案组合使用,可以构建一个相当完整的家长控制系统。但需要注意以下几点:

  • 这些方案需要 root 权限 来配置。如果你的孩子拥有 sudo 权限,ta 理论上可以绕过所有限制。
  • pam_time 只能控制新登录,无法踢出已经在线的用户。需要配合时长检查脚本来处理。
  • iptables 的 owner 模块只能匹配本机进程发出的流量,对于通过代理或 VPN 的流量可能无效。

最后,技术手段只是辅助。与孩子建立良好的沟通和信任,比任何软件限制都更有效。