8
11
2017
2

谁又用掉了我的磁盘空间?——魔改 ncdu 来对比文件树大小变化

磁盘空间不够用了,或者只是洁癖发作想清理了,可以用 ncdu 来查看到底是什么文件占用了磁盘。ncdu 基于 ncurses,对比 du,更方便交互使用,对比 baobab 这类的 GUI 的工具,ncdu 可以在服务器、Android、树莓派、路由器等没有或者不方便有图形界面的地方跑。

但是呢,我现在有很多很多不同时间的备份,我想知道,是什么东西突然用掉了我好几百兆的空间?我是不是需要把它排除在备份之外?

所以呢,我需要一个支持对比的工具。

本来我是打算什么时候有空了自己写一个的,然而我注意到 ncdu 可以把大小信息保存在文件里。其实我只要对比两个 ncdu 产生的文件,然后照着输出一个差异文件就可以了嘛。不用自己遍历文件树,不用自己做界面,多棒!而且也不一定要像我这样有不同时间的备份才有用。可以定时跑一跑 ncdu,把导出的文件保存起来,将来随时取用。

于是有了 ncdu-diff 脚本

然而事情总是不那么顺利。输出文件拿给 ncdu 加载的时候,ncdu 报错了——它不支持负数。我给它加了支持,然后再加载,BOOM!ncdu 挂掉了……有符号整型和无符号整型的事情,还有格式化输出的事情……总之花了一天,它终于不崩溃了。补丁也放在同一仓库了。

ncdu

从上图可以看出,Android 的 app 越更新越大……以及深入之后可以发现,微信的动画表情占了我好多好多的空间,我去删掉它们……

给 Arch Linux x86_64 现成的包:下载, 签名

Category: Linux | Tags: ncurses linux python
6
1
2017
6

WordPress 被入侵有感

吶,昨天说到VPS被报告有攻击行为,后来异常流量被逮到了,经过追查,真相大白。

前天(还是前天,因为又过了一天)分析了异常流量的时间分布之后,发现该流量从上午9点多开始,一直持续。于是我又 netstat -npt 了一下,看到了大量对各网络公司IP 80端口的连接。它还在呢!其实我早该 htop 瞅一眼的说。

发现三四个「php /tmp/tmp」进程,每个进程有大量连接。试图通过 /proc/PID/fd 取得它打开的文件失败,因为都是空的……然后,为了中止攻击,我停了 php-fpm 服务,杀掉了所有 php 进程。杀完才后悔,我连它是哪个用户跑的都没看呢 -_-||| 心急就忘记了应该发 SIGSTOP 信号的。

时间上与任何 cron job 都不匹配。不过我还是检查了可能的 PHP 脚本任务,并没有发现异常。这时 VPS 的主人 Edison 说,是不是 WordPress 的锅?于是他去扫描了一下 WordPress。这个 WordPress 是数年前 Edison 手工部署的,后来并没有怎么用。并不是通过软件仓库安装,所以 dpkg 没有检查出异常,也因此没有任何更新,年久失修。结果检查出来好多个后门。

这些后门都是在 PHP 脚本里加一两句话,对某个特定的 POST 参数进行求值(eval)。简单有效的后门呢。也难怪我怎么都没有找到恶意程序,原来是直接从网络提交过来的,通过 php-fpm fork 了进程出来。

嗯,就是这样。并没有多么神秘,也没能拿到攻击脚本。这件事充分地说明了我坚持不使用 WordPress 是个无比正确的决定 :-)

其实呢,这种攻击对于 Linux 来说是很奇怪的。就像作为 Python 使用者,SQL 注入对我来说是很奇怪的一样。最不安全的也并不是 PHP,而是 WordPress,核心逻辑上的漏洞不补,再怎么从细枝末节上修补也是软弱无力的。

它丫的 www 用户为什么对 WordPress 的代码文件有写权限啊?

它丫的 www 用户为什么对 WordPress 的代码文件有写权限啊?

它丫的 www 用户为什么对 WordPress 的代码文件有写权限啊?

嗯,重要的事情要说三遍。现在互联网越来越险恶,竟然还有著名软件项目不知道 W^X 这个常识我也是醉了……

一点安全常识,给不懂的人:

  • 任何时候,尽力做到权限最小化(不要学360拿 suid 跑 GUI)
  • Web 网站,用户可写目录一定不能被执行,能够执行的目录执行者一定不能有写权限(你看我的 MediaWiki 曾经暴露在外网那么久也只是招来了一些 spam,从来没人能远程执行代码)
  • 尽量使用发行版提供的软件包,及时更新,特别是对于没有充分时间关注和维护的东西

还有,我还挺想念 systemd 的,直接 systemctl status 就能知道进程属于哪个服务了。而且可以几行配置就把不需要的权限干掉~

Category: Linux | Tags: WordPress PHP Linux
4
23
2017
15

UDP: 谁动了我的源地址?

最近 #archlinux-cn 又流行玩 teeworlds 了,然而我却连不上那个服务器。

情况很奇怪。我能 ping 通服务器 IP,TCP 连接也正常,UDP traceroute 也表现得很正常(对关闭端口能够完成,对开放端口会在最后一跳开始得到一堆星号),并且我连接的时候,服务器能看到我在连接。也就是说,TCP 和 ICMP 都正常,UDP 上行正常,下行出了状况。

难道是有防火墙?首先呢,我能连接其它服务器,说明我这边没有问题;大部分人能连接上服务器,说明服务器那边也没有问题。所以,问题出在路上。也确实有另外的北京联通用户连不上这个服务器。但是很奇怪啊,为什么单单只是这一个 IP 的 UDP 包丢失了呢?

于是继续试验。从最简单的开始,用 netcat / socat 尝试通讯。方向反过来,我监听,服务器那边连接。端口是我在路由器上做过端口映射的。结果是正常的。再来,服务器那边监听,我往那边发,果然我就收不到包了。按理说,UDP 双方是对等的,不应该换了个方向就出问题呀。难道是因为端口映射?Wireshark 抓包看到本地使用的端口号之后,在路由器上映射一下,果然就通了!

然后,我注意到了一件十分诡异的事情:虽然我和服务器能够通讯了,但是我的 Wireshark 上只显示了我发出去的包,却看不到回来的包!我抓包时按服务器 IP 做了过滤,所以,回来的包的源 IP 不是服务器的地址!

重新抓包一看,果然。服务器 IP 是 202.118.17.142,但是回来的包的源 IP 变成了 121.22.88.41……看起来这是联通的设备,在下行 traceroute 时能够看到有节点与它 IP 相似(121.22.88.1)。原来又是这著名的「联不通」又干坏事了 -_-|||

虽然 socat 接收 UDP 时不介意源 IP 变化了,但是 teeworlds 介意啊。并且 NAT 那边也会不知所措。所以,首先得告诉路由器把来自这个 IP 的 UDP 包全部扔给我:

ssh 192.168.1.1 iptables -I FORWARD -i ppp0.2 -p udp -s 121.22.88.41 -j ACCEPT

于是数据包有了。接下来是修正源 IP。我试过 SNAT,无效。这东西似乎只对本地发出的包有用?于是我又用 netfilter_queue 了。这东西很强大呢~一个简单的 Python 脚本搞定:

#!/usr/bin/env python3

from netfilterqueue import NetfilterQueue
from scapy.all import *

def main(pkt):
  p = IP(pkt.get_payload())
  # print('recv', p)
  p.src = '202.118.17.142'
  p.chksum = None
  p[UDP].chksum = None
  pkt.set_payload(bytes(p))
  # print('fixed to', p)
  print('.', flush=True, end='')
  pkt.accept()

conf.color_theme = DefaultTheme()
nfqueue = NetfilterQueue()
nfqueue.bind(1, main)
try:
  nfqueue.run()
except KeyboardInterrupt:
  pass

然后是 iptables 命令:

sudo iptables -I INPUT -s 121.22.88.41 -p udp -j NFQUEUE --queue-num 1 --queue-bypass

scapy 这个神奇的网络库在 Arch 官方源里叫「scapy3k」。Python 的 netfilterqueue 模块需要用我自己修改过的这个版本

2017年7月30日更新:Python 的依赖有点麻烦,所以我又写了个 Rust 版本,放在 GitHub 上了

Category: 网络 | Tags: linux python 网络 iptables Rust
4
15
2017
0

卸载被挂载点掩蔽的挂载点

刚刚遇到一件很囧的事情:我在 /run/user/1000/cache 挂载了我的 SSD,用作火狐和 neocomplete 的缓存。/run/user/1000 这个目录是 systemd 为用户创建的,用来放那些只在运行时有用的文件,比如 pid 文件啦、套接字啦之类的。把挂载点放这里,很显然可以避免为其在磁盘上创建目录,又不必和 /tmp 里的一堆临时文件混在一起。

然而这一次,出大事了!我的火狐启动不了了!我的 Vim 也报了一堆错!细看下来,发现 /run/user/1000/cache 没了……

因为需要 root 权限,/run/user/1000/cache 是在 /etc/rc.local 里挂载的。这一次,它抢先挂载了 /run/user/1000/cache,然后我登录,systemd 帮我挂载了 /run/user/1000。就是下边这个样子:

├─/run                           run        tmpfs          rw,nosuid,nodev,relatime,mode=755                                                shared
│ ├─/run/user/1000/cache         test       zfs            rw,xattr,posixacl                                                                shared
│ └─/run/user/1000               tmpfs      tmpfs          rw,nosuid,nodev,relatime,size=804780k,mode=700,uid=1000,gid=1000                 shared
│   └─/run/user/1000/gvfs        gvfsd-fuse fuse.gvfsd-fus rw,nosuid,nodev,relatime,user_id=1000,group_id=1000                              shared

WTF!这样我就访问不到它了呀!我一开始还以为我的 SSD 又出什么状况了呢,结果是这样,挂载上了,但是访问不到……而因为访问不到,所以也没法卸载……

当然啦,我可以先把 /run/user/1000 和下边的那个 gvfs 给卸载掉。但那样做,我不确定 systemd、PulseAudio、D-Bus 它们会有多生气。bind mount 也尝试了,然而并没有什么用。它只能用来访问被挂载点掩蔽的文件,访问不到被挂载点掩蔽的挂载点。

然后我想到了之前玩过的网络命名空间。当然这次需要的是之前没仔细探索的挂载命名空间了。

直接 sudo unshare -m 进去,findmnt -o+PROPAGATION 发现全部都是 private 的,也就是 umount 了不影响外边。于是我就可以把 /run/user/1000 这个树卸载掉啦。然后 mount --make-shared /run/user/1000/cache 把它变成 shared 状态,再卸载,应该就可以把外边那个也卸载掉了吧?

No。失败了。研究了半天 unshare、mount_namespace 的文档之后确认,把 private 的挂载点变成 shared 之后,会创建一个新的「共享组」,而只有在同一个「共享组」里的挂载点才会相互传播。所以,unshare 你别把我的挂载点都变成 private 了好么?

文档下翻,它还真有这么个选项:

sudo unshare -m --propagation shared

然后里外执行这条命令,确认一下「shared:」后边那个数字是一致的:

# cat /proc/self/mountinfo | grep zfs
282 281 0:47 / /run/user/1000/cache rw shared:137 - zfs test rw,xattr,posixacl

没问题了。先 mount --make-private /run/user/1000 等把它们变成私有的,卸载掉,再把 /run/user/1000/cache 给卸载掉。来外边一看,果然被卸载掉啦~

(然后我还是为其在磁盘上专门建立个目录防止出问题好了。zfs,不知道怎么写 systemd 的 .mount 文件。)

Category: Linux | Tags: linux
3
14
2017
18

我的 zsh 提示符

这是我用了多年的 zsh 提示符。

My zsh prompt

右提示符比较简单,先说。

首先,这个右提示符是 zsh 才支持的,不是 hack 左提示符来的哦。

我的右提示符显示的是(提示符打印出来时的)时间。在有后台任务时,会在左边以黄色显示出后台任务的数量,增加些许后台默默工作的进程的存在感啦。

截图中可以看到,只有最后一行才显示了右提示符(以至于我截图都得 hack 一下)。我使用了setopt transient_rprompt,这样 zsh 会清掉旧的右提示符,就不会影响复制了。以前每次复制时都带上一堆空格然后几个时间,折行之后根本没法看,后来才发现体贴的 zsh 已经有这么个选择了。

另外,在输入命令到右提示符时,右提示符会自动消失,以免和命令混淆。都说了很体贴的哦~

左边,是一个两行的提示符。之所以做成两行,是为了保持命令的起始位置不会因为提示符的长度变化而变化,每次输入新命令的时候,光标都在同一列,易读好找。我就不明白,那些坚持 bash 默认提示符的人是怎么坚持下来的,用着用着不知道自己光标去哪里了……对了,zsh 在输出提示符时,会保证它从终端最左边那一列开始输出。如果上一行不完整,zsh 会打印一个反色的「%」来表示(截图里 ^C 那里就有一个)。

蓝色「>>> 」是学 Python 的,但是使用了蓝色以免和 Python 混淆。如果是 root 用户,则显示红色的「### 」以警示。这个比较刺眼,所以就尽量不用 root 跑 shell 啦。

第一行开头是命令序号,就是历史记录里有多少条命令。每执行一条命令它就会加一,空行或者 Ctrl-C 放弃的不算。其实没什么用的样子。

然后是一个用于标识不同机器的名字。比如这里 lilywork 表示我正在我的工作机上。我家里那个系统里不会显示这个。这个信息可以通过ZSH_PS_HOST变量来设置,比如一般可以设置成$(hostname)。GitLab 之前的提示符里大概没有这个吧。

再就是最后一条命令的状态码($?)。如果命令成功就不显示,否则显示一个红色的数字,以提示上条命令出错了。所以说了嘛,我没法理解坚持使用 bash 及其默认提示符的人……

然后是缩短过的当前目录。~tmp是我的临时目录,有名字(hash -d tmp=....)的。但是它不会缩短中间路径的名字,反正我在它下边写命令,不用担心路径太长。不过我不建议深入探索 nodejs 的模块树,显示好几行的路径并不好看的。

最后一项又是可选的,git 当前分支。这个功能是我自己写的,不是 zsh 自带的那个,是异步显示的哦~忙着干活呢,不能在这种小事上浪费时间、中断思绪嘛。并且还可以通过设置来排除一些目录,比如访问特别慢的远程目录,比如已经死掉很久的 Wuala。

显示的信息不多,也一点都不华丽,但十分有用呢。

介绍完毕,提示符的定义我这里就不写啦。代码都在这里:https://github.com/lilydjwg/dotzsh

Category: shell | Tags: zsh linux
2
25
2017
17

中键的功能

鼠标中键,就是左键和右键之间的那个键啦。常见的鼠标上它在滚轮上。所以你知道了,滚轮是可以往下按的哦。如果是触摸板并且没有中键的话,可以配置双指点击来作为中键使用的(synclient ClickFinger2=3)。

中键具有以下好用的功能哦~(括号里是适用的场景)

  • 粘贴选择区,不用按复制和粘贴的快捷键了~不过选择区的寿命通常比较短,只适合快速的粘贴操作。另见 X Window 中的剪贴板一文。(Linux 桌面、macOS 终端、gpm)
  • 在后台新标签页打开链接(火狐、Google Chrome 等浏览器都支持)
  • 关闭标签页(基本上也是用于网页浏览器。我自己的 GVim 也支持)
  • 定位滚动条,可以快速地定位到开头、结尾,或者之前的位置。不需要拖来拖去的麻烦。可惜 GTK 3 里这个功能不好用的了。(GTK 2、Qt)
  • 移动画布(GIMP、Inkscape 等作图软件、GNOME 的文档查看器 Evince)

这只是比较通用的功能。我的 Awesome 还配置了使用中键关闭窗口呢(「关闭标签页」语义的扩展)。火狐的一些菜单项也支持中键点击,比如书签菜单,右键的「查看图像」菜单,比如前进/后退按钮,以及在它上边点击右键出来的历史记录项目。

总结一下中键的语义:

  • 在可以粘贴的地方,粘贴
  • 在打开对象时,打开新对象而不取代已有者
  • 在打开的对象本身上时,关闭之
  • 在可定位对象上,移动之
Category: Linux | Tags: linux X Window X window
12
22
2016
9

利用 systemd 的 watchdog 功能重启卡住的服务

我在用 offlineimap。用着用着就发现一个问题:偶尔 offlineimap 会卡在网络上不动弹了。跟 getmail 一个德性……

但是 offlineimap 又跟 getmail 有点不一样,它是持续运行着的。虽然非要把之前那个 killhung 程序拿来用不是不可以,但我还是重新弄了一个更优雅的方案:systemd watchdog。

我的 offlineimap 本来就是用 systemd 服务的方式来跑的,所以很适合这样的改造呢。只是,当我瞅了一眼源码之后,我就放弃了 patch offlineimap 的打算。很难在合适的地方添加 watchdog 相关的代码。

既然从内部着手不好做,那就从外部写一个 wrapper 好了,反正 offlineimap 跟 getmail 不一样,正常情况下一直在输出东西,就把这个作为它的「心跳」特征好了。当然这个 wrapper 还可以给其它程序用。

于是,watchoutput 程序诞生了!稍微改一下 offlineimap 的 .service 文件,像这样子就好了:

[Unit]
Description=Offlineimap Service

[Service]
Type=notify
ExecStart=.../watchoutput /usr/bin/offlineimap
TimeoutStopSec=3s
SyslogIdentifier=offlineimap
Restart=on-failure
WatchdogSec=70
LimitCORE=0

[Install]
WantedBy=default.target

加上LimitCORE=0是为了阻止重启的时候由于 SIGABRT 信号导致 coredump,浪费磁盘空间。

用了几天之后,终于观察到一次由 watchdog 触发的重启:

12月 19 12:26:53 lilywork offlineimap[21623]:  Establishing connection to imap.exmail.qq.com:993 (main-remote)
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Watchdog timeout (limit 1min 10s)!
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Killing process 21623 (python3) with signal SIGABRT.
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Killing process 21625 (offlineimap) with signal SIGABRT.
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Main process exited, code=dumped, status=6/ABRT
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Unit entered failed state.
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Failed with result 'core-dump'.
12月 19 12:28:03 lilywork systemd[687]: offlineimap.service: Service hold-off time over, scheduling restart.
12月 19 12:28:03 lilywork systemd[687]: Stopped Offlineimap Service.
12月 19 12:28:03 lilywork systemd[687]: Starting Offlineimap Service...
12月 19 12:28:04 lilywork systemd[687]: Started Offlineimap Service.

没过几天,我又给这个 watchoutput 的脚本找到另外的用处:自动重启网络。

我家里的笔记本连 Wi-Fi 不知怎么,这些天经常会卡住(只发不收,一直处于 ARP 找网关的状态)。内核之前报过一次错,现在也没反应了。

于是:

[Unit]
Description=Watch for network availability

[Service]
Type=notify
ExecStart=.../watchoutput --retry-on-exit 2 --wait-before-retry 30 --ignore-stderr \
    -- ping -i 30 192.168.1.1
Restart=on-failure
WatchdogSec=70
StandardOutput=null
StandardError=journal
LimitCORE=0
SyslogIdentifier=watch-network

[Install]
WantedBy=default.target

拿 watchoutput 监控 ping 网关的输出,每30秒 ping 一次,如果70秒还没反应就重启它自己。然后我们还需要重新连接网络。在 /etc/systemd/system 下建立 netctl-auto@wlan0.service.d 目录,并在其下建立一个 watchdog.conf 文件,给 netctl-auto@wlan0.service 服务增加一项配置:

[Unit]
PartOf=watch-network.service

这样当 watch-network.service 重启的时候,netctl-auto@wlan0.service 就会自动重启了~

Category: Linux | Tags: linux systemd
11
10
2016
14

数据让 git 给吃了!

之前一直觉得 git 是很安全的,除非用户显式指定(比如 --force 啦,reset --hard 啦,checkout xxxx 啦),git 在用户会失去数据时都会停下来,让不小心的用户有机会处理被遗忘的修改。直到有一天,我们有个文件让 git 给吃了!

嗯,是「我们」,不是「我」。这是我们的代码部署服务器上出的事。这仓库不是我使用的,整个操作流程我也没有参与设计与评估。实际上我只是作为 troubleshooter 参与到这次神秘事件之中的。

要让 git 愉快地吃掉数据,只要这样就可以了:

  • 提交 A 不包含文件 f
  • 提交 B 包含文件 f
  • 当前工作区为提交 A,并且包含一份未被 git 管理的文件 f,并且 f 被 gitignore 忽略掉了

然后做如下操作,未被管理的那份 f 就会消失不见了:

  • 将工作区切换到提交 B。因为 f 被忽略,所以 git 不会报错(代码
  • 将工作区再切换回 A。因为 A 不包含 f,所以 f 被删掉了

正在吃 f 的 git:主人遗弃了的 f 就交给我好了~

要避免出现这种问题,当然是在 git 工作区会有修改的时候,不要依靠 git 来在多个版本间切换啦~btrfs 或者 zfs 的快照多好!如果文件系统不支持快照的话,那就用多个目录吧。

Category: 版本控制 | Tags: linux Git
10
21
2016
0

在 Python 里设置 stdout 的编码

有时候进程的运行环境里,locale 会被设置成只支持 ASCII 字符集的(比如 LANG=C)。这时候 Python 就会把标准输出和标准错误的编码给设置成 ascii,造成输出中文时报错。

一种解决办法是设置支持 UTF-8 的 locale,但是那需要在 Python 进程启动前设置。启动之后,初始化过了,再设置 locale 也不会重新初始化那些对象。

另一种办法是往 sys.stdout.buffer 这种地方直接写 bytes。理论上完全没问题,但是写起程序来好累……

我就去找了一下怎么优雅地弄一个新的 sys.stdout 出来。Python 3 的 I/O 不再使用 C 标准库的 I/O 函数,而是直接使用 OS 提供的接口。封装位于 io 这个模块里边,有带缓冲的,不带缓冲的,二进制的,文本的。

研究了一下文档可知,sys.stdout 是个 io.TextIOWrapper,有个 buffer 属性,里边是个 io.BufferedWriter。我们用它造一个新的 io.TextIOWrapper,指定编码为 UTF-8:

import sys
import io

def setup_io():
  sys.stdout = sys.__stdout__ = io.TextIOWrapper(
    sys.stdout.detach(), encoding='utf-8', line_buffering=True)
  sys.stderr = sys.__stderr__ = io.TextIOWrapper(
    sys.stderr.detach(), encoding='utf-8', line_buffering=True)

这里除了可以设置编码之外,也可以设置错误处理和缓冲。所以这个技巧也可以用来容忍编码错误、改变标准输出的缓冲(不需要在启动的时候加 -u 了)。

其实这样子还是不够彻底。Python 在很多地方都有用到默认编码。比如 subprocess,指定 universal_newlines=True 时 Python 会自动给标准输入、输出、错误编解码,但是呢,在 Python 3.6 之前,这里的编码是不能手动指定的。还有参数的编码,也是不能指定的(不过可以传 bytes 过去)。

所以,还是想办法去设置合适的 locale 更靠谱……

Category: python | Tags: Python 中文支持 linux
9
13
2016
7

Linux 下的 Wi-Fi 分享

首先看看你的网卡和驱动组合是否支持这样的操作。

>>> iw list | grep -A2 combinations:
        valid interface combinations:
                 * #{ managed } <= 1, #{ AP, P2P-client, P2P-GO } <= 1, #{ P2P-device } <= 1,
                   total <= 3, #channels <= 2

上边这个输出说明支持,并且频道可以不一样。

然后,添加一个用途 AP 的网络接口,并配置 IP 地址。我的无线网络接口名字是 wlan0,因为我通过创建空 /etc/udev/rules.d/80-net-setup-link.rules 文件的方式禁用了 systemd 的网络接口改名。

sudo iw dev wlan0 interface add wlan0_ap type __ap
sudo ifconfig wlan0_ap 192.168.17.1

配置 NAT:

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo iptables -w -t nat -A POSTROUTING -s 192.168.17.0/24 -j MASQUERADE

配置 DHCP。我用的是 dnsmasq。它本来是作为 DNS 缓存用的,但是也支持 DHCP,那就用它了:

interface=wlan0_ap
no-dhcp-interface=wlan0
dhcp-range=192.168.17.50,192.168.17.150,12h

注意不要在其它只提供 DNS 服务的接口上提供 DHCP 服务,以免出现冲突。

然后就可以开启热点啦。hostapd 配置如下:

interface=wlan0_ap
driver=nl80211
ssid=名字
channel=1
hw_mode=g
ieee80211d=1
country_code=cn
ieee80211n=1
ieee80211h=1
ignore_broadcast_ssid=0
auth_algs=1
wpa=2
wpa_passphrase=secret
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

最后把它们跑起来就可以了。

为了方便使用,我创建了个 systemd 服务 wlan0_ap.service:

[Unit]
Description=Setup wlan0_ap
Before=hostapd.service
After=sys-subsystem-net-devices-wlan0.device
After=iptables.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/iw dev wlan0 interface add wlan0_ap type __ap
ExecStart=/usr/bin/ip address add dev wlan0_ap 192.168.17.1/24
ExecStart=/usr/bin/iptables -w -t nat -A POSTROUTING -s 192.168.17.0/24 -j MASQUERADE
ExecStop=-/usr/bin/iptables -w -t nat -D POSTROUTING -s 192.168.17.0/24 -j MASQUERADE
ExecStop=/usr/bin/ip address delete dev wlan0_ap 192.168.17.1/24
ExecStop=/usr/bin/iw dev wlan0_ap del

[Install]
WantedBy=hostapd.service

systemctl enable wlan0_ap 之后就可以直接 systemctl start hostapd 来启动了~当然也很容易停止服务:systemctl stop hostapd wlan0_ap。我的 dnsmasq 总是开启的,所以就不用加依赖了。还有 ipv4_forward 我也是早就写到配置文件 /etc/sysctl.d/99-sysctl.conf 里的。

Category: Linux | Tags: linux 网络 systemd

部分静态文件存储由又拍云存储提供。 | Theme: Aeros 2.0 by TheBuckmaker.com