Marco Nie https://blog.niekun.net/ zh-CN you are the company you keep... Mon, 01 Jul 2024 10:17:13 +0800 Mon, 01 Jul 2024 10:17:13 +0800 使用虚拟环境 env 开发 python https://blog.niekun.net/archives/env-python.html https://blog.niekun.net/archives/env-python.html Mon, 01 Jul 2024 10:17:13 +0800 admin 使用虚拟环境进行Python开发有助于隔离项目的依赖,避免不同项目之间的库版本冲突。以下是如何创建和使用虚拟环境的详细步骤。

Python 3.3 及以上版本自带 venv 模块,可以直接使用。

使用 venv 创建虚拟环境

创建虚拟环境

在你的项目目录下,运行以下命令来创建一个虚拟环境,这将在项目目录下创建一个名为 myenv 的文件夹,其中包含虚拟环境的所有文件:

python -m venv myenv

激活虚拟环境

Windows:

myenv\Scripts\activate

macOS 和 Linux:

source myenv/bin/activate

安装依赖

在虚拟环境中,你可以使用 pip 来安装项目所需的库:

pip install requests

安装的库将只会影响当前虚拟环境,而不会影响系统的 Python 环境或其他项目。

冻结依赖

为了确保你的项目依赖可以在其他环境中重现,你可以使用以下命令将当前环境的依赖写入 requirements.txt 文件:

pip freeze > requirements.txt

requirements.txt 文件将包含所有当前环境中的安装包及其版本信息。

使用 requirements.txt 安装依赖

在新的环境中,你可以使用 requirements.txt 文件来安装所需的所有依赖:

pip install -r requirements.txt

退出虚拟环境

当你完成工作时,可以通过以下命令退出虚拟环境:

deactivate

使用虚拟环境进行Python开发可以有效地隔离项目依赖,避免版本冲突。通过创建和激活虚拟环境、安装依赖、冻结依赖并在新环境中重新安装依赖,可以确保你的项目在不同环境中具有一致的运行表现。

]]>
0 https://blog.niekun.net/archives/env-python.html#comments https://blog.niekun.net/feed/archives/env-python.html
服务器装 warp 解锁 chatgpt https://blog.niekun.net/archives/Linux-warp.html https://blog.niekun.net/archives/Linux-warp.html Thu, 27 Jun 2024 15:12:00 +0800 admin 最近在使用 chatgpt 中发现 ios 端无法登录 app,网页端正常使用。提示信息为:

Something went wrong. You may be connected to a disallowed ISP If youare using VPN, try disabling it. Otherwise try a different Wi-Fi network or data connection。

经过查询发现是我的 vps 服务商只提供网页端 chatgpt 解锁,不支持 app 端。由于 chatgpt 服务也是通过 cloudflare 的 cdn 服务,所以通过将流量转发到 warp 来访问就可以解决问题。

首先需要在服务端安装官方的 warp 命令行工具:warp-cli。

官方教程:https://developers.cloudflare.com/warp-client/get-started/linux/

官方手动添加包仓库教程:https://pkg.cloudflareclient.com/#ubuntu

安装

在命令行输入以下指令来安装第三方仓库并安装包:

# Add cloudflare gpg key
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg

# Add this repo to your apt repositories
echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list

# Install
sudo apt-get update && sudo apt-get install cloudflare-warp

配置

安装好后需要注册一个新账户:

warp-cli registration new

查看当前账户信息:

warp-cli registration show

更换新的 license:

warp-cli registration license xxxxx-xxxxxx-xxxxxx

然后需要设置代理模式,可选有:warp, doh, warp+doh, dot, warp+dot, proxy, tunnel_only。

我只想要它提供一个 socks5 代理端口即可,所以设置为 proxy 模式,它会在本地 40000 端口监听:

warp-cli mode proxy

启动 warp:

warp-cli connect

此时 warp 会在本地 40000 端口建立一个 sock5 代理,只需要将需要转发的流量转发到此端口即可走 warp。并且 warp 会自动配置为 Always On 模式,开机自动运行代理。

查看 warp 当前配置:

# warp-cli settings
Merged configuration:
(derived)       Always On: true
(default)       Switch Locked: false
(user set)      Mode: WarpProxy on port 40000
(Not set)       WARP tunnel protocol: Wireguard
(default)       Disabled for Wifi: false
(default)       Disabled for Ethernet: false
(Not set)       Resolve via: cloudflare-dns.com @ [162.159.36.1, 2606:4700:4700::1111]
(Not set)       qlog logging: Disabled
(default)       Onboarding: true
(API defaults)  Exclude mode, with hosts/ips:
  10.0.0.0/8
  100.64.0.0/10
  169.254.0.0/16
  172.16.0.0/12
  192.0.0.0/24
  192.168.0.0/16
  224.0.0.0/24
  240.0.0.0/4
  239.255.255.250/32
  255.255.255.255/32
  fe80::/10
  fd00::/8
  ff01::/16
  ff02::/16
  ff03::/16
  ff04::/16
  ff05::/16
  fc00::/7

(default)       Fallback domains:
  intranet
  internal
  private
  localdomain
  domain
  lan
  home
  host
  corp
  local
  localhost
  home.arpa
  invalid
  test
(Not set)       Daemon Teams Auth: false
(default)       Disable Auto Fallback: false
(Not set)       Allow Updates: true

查看代理是否生效:

export ALL_PROXY=socks5://127.0.0.1:40000
curl ifconfig.me

代理工具转发流量

服务端的配置文件需要添加和修改的地方如下:

{
    "outbounds": [
        ...
        {
            "protocol": "socks",
            "settings": {
                "address": "127.0.0.1",
                "port": 40000
            },
            "tag":"socks_out"
        }
    ],
    "router": {
        "domainStrategy": "AsIs",
        "rule": [
            ...
            {
                "tag": "socks_out",
                "geoDomain": [
                    {
                        "code": "openai",
                        "filePath": "geosite.dat"
                    }
                ],
                "domainMatcher": "mph"
            }
        ]
    },
    "inbounds": [
        {
            "protocol": "vmess",
            ...
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            },
            ...

注意需要安装扩展版的 geosite.dat 才有 openai 的条目:https://github.com/Loyalsoldier/v2ray-rules-dat

通过访问以下网址测试是否已经解锁 ios app 端:https://ios.chat.openai.com/public-api/mobile/server_status/v1

以上就是解决 chatgpt 无法访问的方法。

]]>
1 https://blog.niekun.net/archives/Linux-warp.html#comments https://blog.niekun.net/feed/archives/Linux-warp.html
蜗杆基础知识 https://blog.niekun.net/archives/2999.html https://blog.niekun.net/archives/2999.html Mon, 24 Jun 2024 09:51:49 +0800 admin http://www.qsjsj.com/zhinan/ptyzwgcdfljjgff.html
https://domm.muzing.top/chapter_11#pu-tong-yuan-zhu-wo-gan-chuan-dong-de-ji-ben-can-shu-ji-qi-xuan-ze
https://m.cadhome.net/news/proejc/716.html
http://www.qsjsj.com/zhinan/AJMDWGJYHYZWGCSJSGS.html
http://www.lyfy.net/wheel/ptcwstyle.htm

]]>
0 https://blog.niekun.net/archives/2999.html#comments https://blog.niekun.net/feed/archives/2999.html
屏蔽 quic 流量 https://blog.niekun.net/archives/openwrt-quic.html https://blog.niekun.net/archives/openwrt-quic.html Sat, 01 Jun 2024 15:53:42 +0800 admin 最近在使用一些服务的时候发现流量没有正确的按照设定的规则走,发现部分网站已经优先支持 quic 也就是 http3 协议了,而这种协议目前一些客户端无法正确解析。解决方法就是将 quic 流量屏蔽掉,让那些网站强制走 http 或 http2 即可。

quic 协议走的是 udp 层,一般是 443 或 80 端口。

openwrt 或其他 linux 系统上使用 nftables 设置规则即可:

新建路由表
nft add table ip tabletest

# 局域网流量屏蔽
# 局域网流量目标地址是外部地址时传输路径为 prerouting -> forward -> postrouting hooks
nft add chain ip tabletest prerouting { type nat hook prerouting priority 0 \; policy accept \; }
nft add rule ip tabletest prerouting udp dport { 80, 443 } drop

# 本机网关流量屏蔽
# 本机网关流量目标地址时外部地址时传输路径为 本机 -> output -> postrouting hooks
nft add chain ip tabletest output { type nat hook output priority 0 \; policy accept \; }
nft add rule ip tabletest output udp dport { 80, 443 } drop

在 Chrome 中禁用 HTTP/3:

  • 打开 Chrome 浏览器
  • 在地址栏输入 chrome://flags 并按回车。
  • 在搜索框中输入 quic。
  • 将 Experimental QUIC protocol 设置为 Disabled。
  • 重启浏览器。

在 Firefox 中禁用 HTTP/3:

  • 打开 Firefox 浏览器。
  • 在地址栏输入 about:config 并按回车。
  • 接受风险提示。
  • 搜索 network.http.http3.enabled。
    -将其值设置为 false。
]]>
0 https://blog.niekun.net/archives/openwrt-quic.html#comments https://blog.niekun.net/feed/archives/openwrt-quic.html
修改 pip 为国内源 https://blog.niekun.net/archives/pip.html https://blog.niekun.net/archives/pip.html Thu, 30 May 2024 20:02:55 +0800 admin 一键替换命令:

# 清华源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 阿里源
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

# 腾讯源
pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple

# 豆瓣源
pip config set global.index-url http://pypi.douban.com/simple/

# 换回默认源
pip config unset global.index-url
]]>
0 https://blog.niekun.net/archives/pip.html#comments https://blog.niekun.net/feed/archives/pip.html
nftables 使用教程 https://blog.niekun.net/archives/nftables.html https://blog.niekun.net/archives/nftables.html Wed, 08 May 2024 10:14:00 +0800 admin 新版本的 openwrt 使用 fw4 防火墙,默认已经从 iptables 切换到了 nftables,语法有了很大的变化,下面介绍 nftables 的使用方法。

路由表配置

路由表是 nftables 中最顶层的容器,它管理着 chains, sets, maps, flowtables, 和 stateful objects.

family 集合

每个路由表都只能属于一个 family 集合,可用的 family 有:

  • ip 监听 ipv4 的流量
  • ip6 监听 ipv6 的流量
  • inet 同时监听 ipv4 和 ipv6 的流量
  • arp 监听 ARP-level 地址解析协议的流量
  • bridge 监听 bridge 桥接流量 如交换机
  • netdev 用于监听某个单独网卡的流量

基本语法

新建路由表:

nft add table ip tabletest

以上命令在 ip 集合中新建一个名称为 tabletest 的路由表,可以处理 ipv4 流量

路由表列表:

# 列出所有路由表
nft list tables

# 列出所有 ip 集合的路由表
nft list tables ip

删除一个路由表:

nft delete table ip tabletest

路由链配置

不同于 iptables,nftables 没有预定义的链,如 input output 等。想要在某个环节处理流量,需要定义一个自定义名称的基本链,然后将其挂载在一个特定的 netfilter hook 钩子上。下图是流量包在 linux 网络中的传输路径:
image.png

外部访问流量传输到本机后如果目标地址是本机,流量传输路径是 prerouting -> input hooks -> 本机,然后经过本机处理后流向 本机 -> output -> postrouting hooks

如果传入本机的外部流量目标地址不是本机,则受 forward hook 监听,这类流量的传输路径是 prerouting -> forward -> postrouting

本机访问外部地址的流量传输路径是 本机 -> output -> postrouting hooks

注意如果本机作为 router 路由使用,需要提前开启 ip 转发功能:

echo 1 > /proc/sys/net/ipv4/ip_forward

以下是 netfilter 可用的 chains 和 hooks 列表:
image.png

基本语法

建立基本链,挂载在一个特定 type 的 netfilter hook:

nft add chain [<family>] <table_name> <chain_name> { type <type> hook <hook> priority <value> \; [policy <policy> \;] [comment \"text comment\" \;] }

注意,由于 nft 语法使用了特殊字符,如: ;,在命令行中执行需要加转义符 \。或者可以使用单引号 '` 将 nft 后的语句包起来,以下两种写法效果相同:

nft add chain ip tabletest input { type filter hook input priority 0 \; }
nft 'add chain ip tabletest input { type filter hook input priority 0 ; }'

另一种方法是运行 nft 在交互模式,执行以下命令后就可以不加转义符: nft -i

上面的命令在 tebletest 路由表中新建一个 input 链,挂载在 filter 路由链的 input hook 上。这样就可以监听所有进入本地的流量。

priority 决定了所有链的顺序,例如在 filter input hook 上挂载了多个自定义链,通过 priority 决定其执行顺序。数值越低执行优先级越高,例如 -12, -1, 0, 10。如果给多个挂载在同一个 hook 上的自定义基本链同样的 priority,它们的先后执行顺序就是不确定的。

添加以下命令后就可以在 tabletest 基本链中监听本机输出的流量:

nft 'add chain ip tabletest output { type filter hook output priority 0 ; }'

如果不定义大括号中的内容,也就是不挂载在特定 hook 上,则路由链不会监听任何流量。

policy 定义了默认的策略,可用的默认策略为:acceptdrop,如果路由链中的规则都没有匹配则会应用默认策略:

  • accept 没有匹配到的流量继续在网络层传输
  • drop 没有匹配到的流量被丢弃

type 指定自定义路由链挂载到那个基本 chain,可用的基本链:

  • filter, 用于过滤流量包
  • route, 用于重路由,等同于 iptables 的 mangle 路由链的 output hook (其他 mangle hooks 可以使用 filter 代替)
  • nat, 用于运行 Networking Address Translation (NAT). 只有第一个 nat 流量包会匹配到此链剩余的包会跳过此链,因此尽量不要使用此链过滤流量

hook 定义了挂载的基本链 hook,可用的 hooks 如下:

  • ingress 只能用于 netdev 和 inet family: 监听来自于 NIC driver 的流量, 早于 prerouting.
  • prerouting: 监听所有在 routing 前的入口流量. 流量可能重定向到 local 或 remote systems.
  • input: 监听所有被路由或重定向到 local system 的入口流量
  • forward: 监听所有不被重定向到 local system 的入口流量
  • output: 监听所有在 local machine 被管理的出口流量
  • postrouting: 监听所有被路由后的即将离开 local system 的出口流量

列出一个路由表的所有路由链:

nft list ip table tabletest

列出一个路由表的指定路由链:

nft list chain ip tabletest output

comment 可以给规则添加注释:

nft add rule ip tabletest input counter comment \"test comment\"

基本规则配置

通过规则可以控制路由链上的流量。

基本语法

添加规则:

nft add rule ip tabletest output ip daddr 8.8.8.8 counter

以上命令会在 tabletest 路由表的 output 链中添加一条规则,匹配出口流量中 ip 地址为 8.8.8.8 的流量并对匹配次数计数,nftables 中 counter 会默认启用即使不写。以上命令相当于 iptables 中的 -A 命令。

列出某个链包含的规则:

root@OpenWrt:~# nft list chain ip tabletest output
table ip tabletest {
        chain output {
                type filter hook output priority filter; policy accept;
                ip daddr 8.8.8.8 counter packets 0 bytes 0
        }
}

下面测试以上规则是否生效,执行以下命令:

ping -c 1 8.8.8.8

再次查看此链的规则:

root@OpenWrt:~# nft list chain ip tabletest output
table ip tabletest {
        chain output {
                type filter hook output priority filter; policy accept;
                ip daddr 8.8.8.8 counter packets 1 bytes 84
        }
}

可以看到已经有一次计数了。

指定位置添加规则:
nftables 中必须通过 handle num 编号来在指定位置添加规则,需要通过 -a 查看链中已经存在的规则的编号:

nft -n -a list table ip tabletest

-n 可以按数字顺序排号避免出现重复编号。再次查看链中的规则:

root@OpenWrt:~# nft -n -a list table ip tabletest
table ip tabletest { # handle 4
        chain output { # handle 1
                type filter hook output priority 0; policy accept;
                ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5
        }
}

handle 5 就是这条规则的编号。

下面我们通过 handle 索引在这条规则后添加一条新规则:

nft add rule ip tabletest output position 5 ip daddr 127.0.0.8 drop

查看链中的规则:

root@OpenWrt:~# nft -n -a list table ip tabletest
table ip tabletest { # handle 4
        chain output { # handle 1
                type filter hook output priority 0; policy accept;
                ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5
                ip daddr 127.0.0.8 drop # handle 6
        }
}

如果要在某条规则前插入一条规则需要使用 insert 指令:

nft insert rule ip tabletest output position 5 ip daddr 127.1.1.8 drop

查看效果:

root@OpenWrt:~# nft -n -a list table ip tabletest
table ip tabletest { # handle 4
        chain output { # handle 1
                type filter hook output priority 0; policy accept;
                ip daddr 127.1.1.8 drop # handle 7
                ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5
                ip daddr 127.0.0.8 drop # handle 6
        }
}

在某条链最前面添加一条规则:

nft insert rule ip tabletest output ip daddr 192.168.2.1 counter

在最前面添加规则就不需要指定 handle 了。

替换某条规则:
替换一条规则也需要 handle 编号。下面示例会替换 handle 5 为新的规则:

nft replace rule ip tabletest output handle 5 ip daddr 1.1.1.1

删除规则:
同样的,删除某一条规则也需要获取这条规则的 handle 编号。

删除 tabletest 链的 handle 7 规则:

 nft delete rule ip tabletest output handle 7

删除链中所有规则:

nft flush chain ip tabletest output

删除路由表中所有链的所有规则:

nft flush table ip tabletest

ruleset 层级的操作

显示所有 family 的所有 rule 规则:

nft list ruleset

显示某一个集合的所有 rule:

 % nft list ruleset arp
 % nft list ruleset ip
 % nft list ruleset ip6
 % nft list ruleset bridge
 % nft list ruleset inet

清除所有集合的所有规则:

nft flush ruleset

清除某一个集合的所有规则:

 % nft flush ruleset arp
 % nft flush ruleset ip
 % nft flush ruleset ip6
 % nft flush ruleset bridge
 % nft flush ruleset inet

备份规则到文件:

# 备份所有集合的所有规则
nft list ruleset >> backup.nft

# 备份 ip 集合的所有规则
nft list ruleset ip >> backup.nft

从文件恢复规则:

nft -f backup.nft

以 json 格式显示所有规则:

nft --json list ruleset

流量元信息匹配

通过 meta 选择器可以进行流量匹配或流量设置。下面简单介绍几个常用的匹配模式,更加详细的参考官方资料:https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation

iifname 匹配网卡名称:

# lo 网卡的入口流量会被接收
nft add rule tabletest input meta iifname lo accept

mark 匹配流量标记:

# 流量标记为 123 的出口流量计数
nft add rule tabletest output meta mark 123 counter

skgid 匹配流量由特定 gid 用户产生的数据:

# 匹配来自 gid 用户 1000 的流量
nft add rule tabletest output meta skgid 1000 counter

流量头信息匹配

通过 ip {saddr | daddr} 可以匹配 ipv4 的源流量或目标流量:

# 匹配来自 192.168.1.100 且去往 192.168.1.1 的流量并计数
# 注意本机地址必须为 192.168.1.1 才可以由 input hook 截获
nft add rule ip tabletest input ip saddr 192.168.1.100 ip daddr 192.168.1.1 counter

通过 icmp type 关键词来匹配 icmp 流量,如 ping request:

nft add rule ip tabletest input icmp type echo-request counter drop

可以通过命令查询所有可用的 icmp type 类型:

root@OpenWrt:~# nft describe icmp type
payload expression, datatype icmp_type (ICMP type) (basetype integer), 8 bits

pre-defined symbolic constants (in decimal):
        echo-reply                                         0
        destination-unreachable                            3
        source-quench                                      4
        redirect                                           5
        echo-request                                       8
        router-advertisement                               9
        router-solicitation                               10
        time-exceeded                                     11
        parameter-problem                                 12
        timestamp-request                                 13
        timestamp-reply                                   14
        info-request                                      15
        info-reply                                        16
        address-mask-request                              17
        address-mask-reply                                18

通过 ip protocol 匹配 ip family 任意类型的协议:

# 匹配所有 tcp 流量
nft add rule ip tabletest output ip protocol tcp

# 匹配所有 tcp udp 流量
nft add rule ip tabletest output ip protocol { tcp, udp }

通过 meta l4proto 匹配 inet family 任意类型的协议:

# tabletest 需要定义为 inet 集合
nft add rule inet tabletest output meta l4proto tcp

匹配特定端口的流量:

# 丢弃所有端口为 1-1024 的 tcp 流量访问本机
nft add rule ip tabletest input tcp dport 1-1024 counter drop

流量匹配动作

accept 和 drop

drop 可以对匹配的流量直接丢弃,注意 drop 不能和其他动作组合使用:

nft add rule ip tabletest input ip protocol udp drop

accept 可以对匹配的流量接收,可以和其他动作组合使用 如 counter 计数:

nft add rule ip tabletest input counter accept

reject 流量

不同于 drop,reject 可以在拒绝流量的基础上进行很多其他动作,如返回给源请求地址无法访问的原因等。如果不指定其他动作,默认会返回源地址一个 ICMP/ICMPv6 port unreachable 的流量包。

示例如下:

# 拒绝所有 input 的 udp 流量
nft add rule ip tabletest input ip protocol udp reject

# 拒绝指定流量并返回 icmp host-unreachable
nft add rule ip tabletest input reject with icmp type host-unreachable

icmp 可用如下原因:

net-unreachable: Destination network unreachable
host-unreachable: Destination host unreachable
prot-unreachable: Destination protocol unreachable
port-unreachable: Destination port unreachable (this is the default)
net-prohibited: Network administratively prohibited
host-prohibited: Host administratively prohibited
admin-prohibited: Communication administratively prohibited

jump 跳转到其他 chain

注意只能跳转到同一个路由表的其他 chain。

首先我们新建一个 chain:

nft add chain ip tabletest tcp-chain

然后定义这个链的规则:

nft add rule ip tabletest tcp-chain counter

然后可以定义将所有匹配的流量跳转过去:

ft add rule ip tabletest input ip protocol tcp jump tcp-chain

以上示例实现的就是将所有 input 的 tcp 流量跳转到 tcp-chain 计数,然后就返回原始 input 环节继续流转。

log 日志

通过 log 可以记录匹配到的流量信息,在系统日志中可以查看到。

下面是一个示例,可以记录所有对本机的 ping 请求:

nft add rule ip tabletest input icmp type echo-request log prefix \"New ping request: \" accept

从局域网对本机进行 ping 后,系统日志如下:

Thu May  9 11:58:04 2024 kern.warn kernel: [ 3741.786865] New ping request: IN=br-lan OUT= MAC=00:0c:29:c5:39:8d:00:50:56:c0:00:02:08:00 SRC=192.168.244.2 DST=192.168.244.1 LEN=60 TOS=0x00 PREC=0x00 TTL=128 ID=49655 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=6609

网络地址转换

nat 链类型可以执行网络地址转换的功能,这种链类型有其特有的属性:

  • 流量中只有第一个包会被用来进行匹配规则
  • 流量包中后续的流量不会被检查
  • nat 链类型特有的规则赋予其他链类型会报错

先定义一个 nat 类型的基本链:

nft add chain ip tabletest postrouting { type nat hook postrouting priority 0 \; }

以上定义了一个 nat 类型的基本链挂载在 postrouting hook 上。

snat 表示源地址。

下面的规则可以将来自 192.168.1.0/24 从 eth0 网卡发出的流量在发送出去的时候,将源地址修改为 1.2.3.4

nft add rule ip tabletest postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4

也可以定义一个地址范围:

# 将所有 tcp 流量的源地址都修改为指定的ip范围内
nft add rule ip tabletest postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000

下面介绍如何修改目标地址,再定义一个 nat 类型的基本链:

nft add chain ip tabletest prerouting { type nat hook prerouting priority 0 \; }

以上定义了一个 nat 类型的基本链挂载在 prerouting hook 上。

dnat 表示目标地址。

下面规则会将要进入 eth0 的 tcp 80 443 端口的流量的目标地址改为 192.168.1.120 也就是重定向:

nft 'add rule ip tabletest prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120'

redirect 是一种特殊的 dnat,它会将流量重定向到本机设备上:

nft add rule ip tabletest prerouting tcp dport 22 redirect to 2222

以上规则会将进入的 tcp 22 端口的流量转发到本机 2222端口上。

需要注意的是 redirect 只能应用于 nat 链类型的 prerouting 和 output hooks。

设置流量包元信息

设置 mark 标记:

nft add rule ip tabletest output mark set 123

set 架构

nftables 提供了 set 架构可以用任意支持的选择器来搭建 sets。

匿名 set

匿名 set 是直接定义在 rule 内的 set,它没有特定的名称,也不可以更新 set 中的元素,下面是一个示例:

nft add rule ip tabletest output tcp dport { 22, 23 } counter

{ 22, 23 } 就属于一个匿名 set。规则会去尝试匹配 set 中的每个元素。

非匿名 set

可以通过 nft add set 来创建一个有名称的 set,例如:

nft add set ip tabletest blackhole { type ipv4_addr \; comment \"drop all packets from these hosts\" \; }

blackhole 就是这个 set 的名称,后续可以再 rule 中使用。set 类型指定是 ipv4 数据。set 名称需要小于等于16个字符,comment 注释是可选项。

可用的 type 类型有:
ipv4_addr: IPv4 address
ipv6_addr: IPv6 address.
ether_addr: Ethernet address.
inet_proto: Inet protocol type.
inet_service: Internet service (read tcp port for example)
mark: Mark type.
ifname: Network interface name (eth0, eth1..)

建立好之后就可以往 set 里添加元素了:

nft add element ip tabletest blackhole { 192.168.3.4 }
nft add element ip tabletest blackhole { 192.168.1.4, 192.168.1.5 }

如果要添加一个 ip 网段则需要将 set 定义 flags interval:

nft add set ip tabletest blackhole { type ipv4_addr \; flags interval \; }

然后就可以添加一个 ip 网段了:

nft add element ip tabletest blackhole { 192.168.1.0/24 }

可以查询 set 中现有的元素:

root@OpenWrt:~# nft list set ip tabletest blackhole
table ip tabletest {
        set blackhole {
                type ipv4_addr
                comment "drop all packets from these hosts"
                elements = { 192.168.1.4, 192.168.1.5,
                             192.168.3.4 }
        }
}

下面就可以通过 set 名称在 nftables 规则中应用:

nft add rule ip tabletest input ip saddr @blackhole drop
nft add rule ip tabletest output ip daddr != @blackhole accept

以上就是 natables 的基本用法。

参考链接

nftables HOWTO documentation page
Nftables families
Netfilter hooks
Operations at ruleset level

]]>
1 https://blog.niekun.net/archives/nftables.html#comments https://blog.niekun.net/feed/archives/nftables.html
通过 dnsmasq nftset 和 nftables 对域名流量的控制 https://blog.niekun.net/archives/dnsmasq-nftset-nftables-1.html https://blog.niekun.net/archives/dnsmasq-nftset-nftables-1.html Tue, 07 May 2024 10:31:00 +0800 admin 最近升级路由器系统到 openwrt 23,发现 dnsmasq-full 已经默认不支持 ipset 转而支持 nftset 了,所以之前的教程:通过 dnsmasq ipset 和 iptables 对域名流量的控制 已经不适用新版本系统。

下面介绍如何通过 nfset 和 nftables 实现同样的功能。

首先查看 dnsmasq 版本是否支持 nftset:

root@OpenWrt:~# dnsmasq -v
Dnsmasq version 2.90  Copyright (c) 2000-2024 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack no-ipset nftset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile

可以看到其中有 nftset 字样,如果没有就需要安装 dnsmasq-full,安装教程参考:dnsmasq 使用教程

nftables 提供 set 功能可以在一个路由表中建立特定名称一个 ip 库,并通过命令 ip daddr 索引库里的地址。关于 nftables 的使用教程参考:nftables 使用教程

先建立一个任意名称的路由表:

nft add table tabletest

然后给这个路由表建立一个名称为 iplist 的 ip 库,类型定义为 ipv4 地址:

nft add set ip tabletest iplist { type ipv4_addr\; }

如果要添加一个 ip 网段,必须定义 ip 库属性:flags interval

nft add set ip tabletest iplist { type ipv4_addr \; flags interval \; }

现在就可以给这个 ip 库里添加 ip 地址了,命令如下:

nft add element ip tabletest iplist { 111.22.33.4 };
nft add element ip tabletest iplist { 111.22.33.4/16 };

可以通过命令查看这个 ip 库里包含的所有地址:

root@OpenWrt:~# nft list set ip tabletest iplist
table ip tabletest {
        set iplist {
                type ipv4_addr
                flags interval
                elements = { 111.22.33.4, 111.22.33.4/16 }
        }
}

通过 dnsmasq 配置文件也可以添加指定域名解析出的 ip 地址到 nftset 对应 ip 库列表中,例如在 /etc/dnsmasq.conf 配置文件中添加以下指令:

nftset=/qq.com/4#ip#tabletest#iplist

重启 dnsmasq 服务:

service dnsmasq restart

查询一下 qq.com 的 ip 地址:

root@OpenWrt:~# nslookup qq.com
Server:         127.0.0.1
Address:        127.0.0.1:53

Non-authoritative answer:
Name:   qq.com
Address: 157.255.219.143

再次查看 iplist 表里包含的 ip 地址:

root@OpenWrt:~# nft list set ip tabletest iplist
table ip tabletest {
        set iplist {
                type ipv4_addr
                flags interval
                elements = { 111.22.33.4, 111.22.33.4/16, 157.255.219.143 }
        }
}

可以看到 qq.com 解析出来的 ip 地址已经放入了 iplist 表中。

nftables 可以识别并处理 nftset 表中的 ip 地址,这样就可以做到对指定域名的流量控制。

新建的自定义路由表需要首先指定某个动作链条属于什么动作链类型。如:

# 定义 tabletest 的 output 链,类型为 filter 路由链的动作链 "output"
# 优先级 0 表示:(在任何路由决策前捕获传入数据包)
# 策略为 accept 表示没有匹配流量后继续传入后续路由表及规则进行匹配
nft add chain tabletest output { type filter hook output priority 0 \; policy accept \; }

# 定义 tabletest 的 prerouting 链,类型为 NAT 路由链的动作链 "prerouting"
nft add chain tabletest prerouting { type nat hook prerouting priority 0 \; policy accept \; }

nftables 规则处理 set 库里 ip 地址的流量:

# 屏蔽本机对 iplist 库中 ip 地址的访问
nft add rule tabletest output ip daddr @iplist drop

# 目标地址为 set 库地址的prerouting tcp 流量转发到指定端口
nft add rule tabletest prerouting ip daddr @iplist ip protocol tcp redirect to :1081

列出指定路由表定义的规则:

root@OpenWrt:~# nft list table tabletest
table ip tabletest {
        set iplist {
                type ipv4_addr
                flags interval
                elements = { 111.22.33.4, 111.22.33.4/16, 157.255.219.143 }
        }

        chain output {
                type filter hook output priority filter; policy accept;
                ip daddr @iplist drop
        }

        chain prerouting {
                type nat hook prerouting priority filter; policy accept;
                ip daddr @iplist ip protocol tcp redirect to :1081
        }
}

删除一个路由表:

nft delete table tabletest

删除一个路由表中所有规则,保留路由链定义:

nft flush table tabletest

删除指定路由表中某个路由链中的所有规则:

nft flush chain tabletest output

参考链接

fw4 Filtering traffic with IP sets by DNS
nftables
Simple rule management
Configuring tables
Configuring Shadowsocks rules with nftset in OpenWRT 23

]]>
0 https://blog.niekun.net/archives/dnsmasq-nftset-nftables-1.html#comments https://blog.niekun.net/feed/archives/dnsmasq-nftset-nftables-1.html
解决在 intel 12代以后的 CPU 上 vmwre 虚拟机性能低下问题 https://blog.niekun.net/archives/intel-12-CPU-vmwre.html https://blog.niekun.net/archives/intel-12-CPU-vmwre.html Thu, 18 Apr 2024 13:01:52 +0800 admin 最近更换了新的电脑,是 i7 12700H 的 CPU,按理说比以前的电脑性能好一些,但是导入之前的 vmware 虚拟机后发现运行起来优点卡顿,但是观察主机资源占用很低,cpu 占用也很低,研究了下才发现是由于新款 cpu 采用了大小核设计导致这个问题。

我的这一款是 6 大核 8 小核 20 线程设计。默认情况下启动虚拟机资源分配是交给 windows 主机自己协调的,很可能会分配给小核运行虚拟机导致运行卡顿,资源管理器可以看到 cpu 负载都在后面的小核上:
image.png

解决方法就是以管理员权限运行 vmware,这样 VMware 会自己调度资源使用,优先级大概是大核>小核>超线程。实际效果很明显,基本都运行在了大核上:
image.png

]]>
1 https://blog.niekun.net/archives/intel-12-CPU-vmwre.html#comments https://blog.niekun.net/feed/archives/intel-12-CPU-vmwre.html
openwrt 系统升级 https://blog.niekun.net/archives/openwrt-1.html https://blog.niekun.net/archives/openwrt-1.html Tue, 02 Apr 2024 10:26:03 +0800 admin 小版本升级

小版本升级,例如 19.05-> 19.07。

这种小版本的升级最方便的就是通过 Attended Sysupgrade 功能,可以保留已安装的包和系统设置。最大限度地无缝过渡。官方介绍:https://openwrt.org/docs/guide-user/installation/attended.sysupgrade

需要先安装 Attended Sysupgrade luci 界面包:

opkg install luci-app-attendedsysupgrade

建议使用此功能前依然做一次数据备份。

然后重新登录 luci,在 system - Attended Sysupgrade 找到入口,点击 search for firmware upgrade 即可在线搜索可更新的系统。

大版本升级

最方便的就是通过 luci 界面升级系统,目前支持直接升级的大版本顺序是:19.07 > 21.02 > 22.03 > 23.05

大版本升级改动

openwrt 21https://openwrt.org/releases/21.02/notes-21.02.0

  • WPA3 support included by default
  • TLS and HTTPS support included by default
  • LuCI is now available over HTTPS
  • Initial DSA support replaces the swconfig system
  • New network configuration syntax and board.json change
  • Kernel with container support

openwrt 22:https://openwrt.org/releases/22.03/notes-22.03.0

  • Firewall4 based on nftables,superseding the iptables-based firewall3
  • Dark mode in LuCI

openwrt 23:https://openwrt.org/releases/23.05/notes-23.05.0

  • Switch from wolfssl to mbedtls as default,TLS 1.3 Support
  • Rust Package Support

数据备份

每个版本升级实际上就是重新刷入了一次固件,所以之前的配置文件什么的基本上都会被覆盖,所以系统内修改过的配置最好做一次备份。

打开 luci 界面,选择 system - backup/flash firmware,在 configuration 菜单栏中将需要保存的文件或目录定义出来,然后在 action 菜单栏中选择 backup - generate archive 即可保存备份到本地。

已安装包列表

可以通过 awk 脚本识别出自己手动安装的包列表,方便更新系统后安装回去,下载脚本:https://github.com/richb-hanover/OpenWrtScripts/blob/main/opkgscript.sh

执行以下命令会保存已安装的包列表到 /etc/config/opkg.installed

opkgscript.sh -v write

执行以下命令会识别并安装 /etc/config/opkg.installed 列表中的包:

opkgscript.sh -v install

也可以执行以下 awk 脚本可以单独列出自己手动安装的包列表:

#!/usr/bin/awk -f
BEGIN {
    ARGV[ARGC++] = "/usr/lib/opkg/status"
    cmd="opkg info busybox | grep '^Installed-Time: '"
    cmd | getline FLASH_TIME
    close(cmd)
    FLASH_TIME=substr(FLASH_TIME,17)
}
/^Package:/{PKG= $2}
/^Installed-Time:/{
    INSTALLED_TIME= $2
    # Find all packages installed after FLASH_TIME
    if ( INSTALLED_TIME > FLASH_TIME ) {
        cmd="opkg whatdepends " PKG " | wc -l"
        cmd | getline WHATDEPENDS
        close(cmd)
        # If nothing depends on the package, it is installed by user
        if ( WHATDEPENDS == 3 ) print PKG
    }
}
EOF

保存以上内容到 listuserpackages.awk 文件中并执行即可列出用户自行安装包列表。

下载升级固件

x86 版本的 openwrt 的升级固件就是全新安装时候用的固件,直接在官网下载需要版本的 gz 压缩包即可。

下载地址:https://downloads.openwrt.org/releases/

我下载的是:generic-ext4-combined.img.gz,注意不要解压出来,保留压缩包即可。

进入 luci 的 system - backup/flash firmware 选择 Flash image ,然后选择刚才下载的压缩包即可上传更新,会提示是否保留设置和配置,跨大版本的升级必须取消选择保留数据,否则可能升级失败
image.png

如果升级后卡在 grub 界面说明可能是由于选择了保留配置导致升级失败了,可以参考官方教程通过 failsafe mode 恢复默认配置:Failsafe mode, factory reset, and recovery mode,或者直接重新安装系统。

网络配置

稍等几分钟安装好后你可能会发现 luci 无法在局域网中访问了,这是由于新安装的固件恢复了 network 配置,需要直接到 openwrt 设备上配置网络。

配置教程参考:openwrt network 配置

配置好网络后在局域网设备中可以用 ssh 登录了,此时会发现提示:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:U9XODs/7A4k065pxSMyEtQ2m98v2P0bf/ML0MfzU.
Please contact your system administrator.
Add correct host key in C:\\Users\\Marco Nie/.ssh/known_hosts to get rid of this message.
Offending RSA key in C:\\Users\\Marco Nie/.ssh/known_hosts:6
Host key for 192.168.244.1 has changed and you have requested strict checking.
Host key verification failed.

这是由于更新系统后 ssh 指纹发生了变化,需要删除本地缓存的 openwrt 设备的指纹在登陆,windows 系统 ssh 指纹保存地址为当前用户目录下的 .ssh 文件夹。

升级后续

升级后可以通过之前的脚本列出的已安装包的列表将自己需要的包安装回去,同时将备份数据按照新系统的格式恢复回去。

从 openwrt 21 开始修改了 network 配置文件格式,参考:https://blog.niekun.net/archives/2291.html
从 openwrt 22 开始替换 iptables 为 nftables,需要原始工具的话可以自行安装回去:opkg install iptables

参考链接

Opkg package manager
OpenWRT 19.07 to 21.02.0 upgrade

]]>
0 https://blog.niekun.net/archives/openwrt-1.html#comments https://blog.niekun.net/feed/archives/openwrt-1.html
Linux 查询及编辑用户及用户组 https://blog.niekun.net/archives/Linux.html https://blog.niekun.net/archives/Linux.html Mon, 01 Apr 2024 16:20:00 +0800 admin 查询当前所有用户
compgen -u

查询当前所有用户组

compgen -g

添加一个用户到某个组

sudo usermod -a -G groupName userName
newgrp groupName

删除一个用户从某个组

sudo usermod -G groupName userName
newgrp groupName

用户和组对文件的权限管理参考:chown 和 chmod 管理文件权限

]]>
0 https://blog.niekun.net/archives/Linux.html#comments https://blog.niekun.net/feed/archives/Linux.html