八哥之神前传【9】

自从过去、现在、未来佛都圆寂后,世界进入七鹰劫,人间爱欲繁华,天堂地狱皆被同化。

1976 年,黄金灯在樱国谈恋爱,顺便读研。他本科是读计算机的,理想是实现脑机合一式的意识永生,但由于时代落后,他慢慢意识到,这个技术在他的时代是无法实现的,于是决定改读脑科医学,打算通过克隆加换脑手术让生命延长。

然而现实总是背离理想,这是一个血腥的世界,满地人体器官,即使在大街上散步,他的眼里也都是血红色一片,随时要小心踩到血肉。

血,一片一片一片,拼出你我的缘分。我的爱因你而专生,你的手摸出我的心疼。

由于场面过度血腥,稣吓醒了!

2042 年,床上

圣小开:“你怎么没睡?”

古思:“才几分钟,还没入睡呢?”

圣小开:“什么?爷都已经做了一个梦,吓醒了!”

古思:“什么梦?给我讲讲?”

圣小开:“虽然是梦,但却是真实故事,只不过主角是黄金灯大师。”

1976 年

东湖有个湖心岛叫樱花岛,是谈恋爱的好地方。

黄金灯心想:“去樱花岛吸吸天地灵气,也许我还有救。”

旅游船荷载 26 人,他认真地数了一遍救生衣,确实有 26 个。习惯性地环扫一番,透视人头,都是妖魔鬼怪,突然视线停留在一个美女脸上,有皮肤的,英气逼人,而且似乎也是中国人。

男女之间的故事都从八哥开始……船出八哥,柴油机罢工,老板说:“大家不用慌,很快就到湖心,我们用竹竿撑过去。”

又过了一会儿,船夫感觉竹竿变沉了,好像插到一个东西,提出水面,是一块骨盆……引起恐慌。

黄金灯专业地站出来说:“我上过人体解剖课,这个一定是人类的骨盆,很可能是个 20 岁左右的年轻男子。”

美女也专业地站出来说:“我是实习警察,最近确实有个 21 岁的失踪男子。”

黄金灯:“凶手或帮凶应该是船夫,知道这里深水区里有肉食性鳗鱼,所以把尸体扔到这喂鱼。”

美女:“怎么防止尸体浮起来呢?”

黄金灯:“绑块石头就行。”

2042 年,床上

古思:“好像是个不吉利的开头!”

圣小开:“结尾其实也不太好。”

1976 年,樱花岛

黄金灯:“你好,警官,我是东湖边上医学院的学生,黄金灯。您好像也是中国人?”

美女:“原来是医学院高材生!我爸爸是樱国人,妈妈是中国人,我的中文名叫施付。”

黄金灯:“施付?em……我还是叫你的樱文名吧!”

施付:“哦,那你就叫我京子吧!”

黄金灯:“京子!”心想:“怎么不是惠子……”

施付:“你今天不用上课吗?”

黄金灯:“我晕血,出来放松一下。”

施付:“学医的,还晕血?”

黄金灯:“是我想得太简单了,还没脱敏吧!”

施付:“你刚才不是很淡定?”

黄金灯:“是哦,好像没那么恶心了!咦!我现在看世界,不是血腥模式了!!”

施付:“嗯嗯,你的专业很有用,要加油!”

黄金灯:“京子小姐,你呢?”

施付:“我来祭拜我爸爸,他葬在这岛上。”

黄金灯:“葬在岛上……原来你是富家小姐!怎么当警察呢?”

施付:“我爸爸死于黑帮暗杀,所以我立志要替他报仇,消灭黑帮。”

黄金灯:“好理想。但是以警察的身份报仇,不会有些不方便吗?”

施付:“是的,要以大局为重,不能公报私仇。”

2042 年,床上

古思:“后来他们恋爱了?”

圣小开:“对。大师遇到京子后,开始对解剖脱敏,并苦练小灯飞刀。”

古思:“小灯飞刀?”

圣小开:“是的。小灯飞刀是一种很厉害的武器,他还发明双刀并进。”

古思:“有什么用?”

1976 年,东湖烟花

星空下,黄金灯搂着京子一起看烟花。

黄金灯:“我已经练成小灯双刀!”

施付:“有什么用?”

黄金灯:“我试过单刀瞄准人体模型的心脏,却可能插在骨头上,致死率降低,而用双刀,都撞到胸骨的几率低很多。”

施付:“但是飞刀又不能比枪快呀!”

黄金灯:“飞刀比枪容易弄到,我可以用它保护你。”

2042 年,床上

古思:“理科男的浪漫?”

圣小开:“哈哈,后来大师真的用飞刀帮京子报仇了。”

古思:“他们后来在一起了吧?”

圣小开:“没有。大师后来回国,京子改行在南洋做投资遇到周老师,很狗血地结婚了。所以大师一直称呼周老师为情敌。”

跟 UMU 一起玩 OpenWRT(入门篇20):WOL

需求

家里有个 PC,关机状态,想在公司远程开机,可是家里没人,怎么办?

条件

  • 机器支持并开启 WOL (Wake On LAN)。

  • 机器通过板载网卡连接路由器(USB 有线网卡不行)。

解决

  1. 路由器需要有公网地址,如果没有,请参考《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》做中转,总之需要能 SSH 到路由器上。

  2. 路由器上安装 etherwake 或 wakeonlan。两者差别是:wakeonlan 是个 Perl 脚本,使用 UDP 包,不需要 root 权限。

  • 如果是在 openwrt 直接使用 root 账号,建议用 etherwake。
1
2
3
opkg update
opkg install etherwake
etherwake MAC_ADDRESS_OF_PC
  • 如果是 armbian,建议平时使用非 root,所以推荐 wakeonlan。
1
2
3
sudo apt update
sudo apt install wakeonlan
wakeonlan MAC_ADDRESS_OF_PC

测试

组装 PC 两台、Intel NUC 7i7BNH 一台测试用过。

Armbian 分区优化

问题

Android 电视盒刷 Armbian,分区时,EMMC 前面一部分没被利用,为什么?以及怎么办?

原因

u-boot 是为 Android 设计的,分区是按照 Android 需求分的。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
Partition table get from SPL is :
name offset size flag
===================================================================================
0: bootloader 0 400000 0
1: reserved 2400000 4000000 0
2: cache 6c00000 20000000 2
3: env 27400000 800000 0
4: logo 28400000 2000000 1
5: recovery 2ac00000 2000000 1
6: misc 2d400000 2000000 1
7: boot 2fc00000 2000000 1
8: system 32400000 40000000 1
9: data 72c00000 15f400000 4

其中 reserved 分区放着其它分区的名字、位移、大小等信息,如果被破坏 u-boot 将无法识别分区。

env 分区保存启动脚本,如果被破坏,可能导致系统无法启动。

解决

一般的 Armbian 安装脚本,都会跳过前面的分区,从偏移 700MB 处开始分区。

1
2
3
parted -s "${DEV_EMMC}" mklabel msdos
parted -s "${DEV_EMMC}" mkpart primary fat32 700M 828M
parted -s "${DEV_EMMC}" mkpart primary ext4 829M 100%

作为优化狂,UMU 显然无法接受这样的浪费!

  • cache 分区有 0x20000000 Bytes,也就是 512MiB,拿来做 /boot 分区岂不美哉?

  • logo 分区?不,UMU 不想看启动画面,直接覆盖掉吧!

  • 分区之间还有空闲!也不能放过!

所以,reserved 分区之后到 env 分区之前的全部空间都拿来做 /boot 分区,env 分区之后全部做 / 分区:

1
2
3
parted -s "${DEV_EMMC}" mklabel msdos
parted -s "${DEV_EMMC}" mkpart primary fat32 100MiB 628MiB
parted -s "${DEV_EMMC}" mkpart primary ext4 636MiB 100%

测试

玩客云和斐讯 N1 测试通过。

跟 UMU 一起玩 OpenWRT(入门篇19):检测 WiFi 入侵

问题

我怀疑有人在用工具穷举我的 WiFi 密码,我该怎么确认?

解决

运行 iw event,如果看到频繁出现 new stationdel station 的 log,说明有设备在频繁连接和断开。

如果您的路由器是小米路由器 Pro,则可以用 iwevent 代替 iw event,密码不对的 log 是 had deauthenticated,断开是 had disassociated

安全建议

设置密码时,应该检查一下您的密码是否在“字典”里。字典参考:

rockyou.txt contains 14,341,564 unique passwords, used in 32,603,388 accounts.

举个例子吧!稣打算用 10 个 0 做密码,先查一下……嗯哼!

valentine
idontknow
pikachu
little
diamond1
iloveu1
babyphat
peanut1
kittens
goddess
ballet
damien
nascar
171717
rangers1
winston
0000000000
rocky1
coolgirl
maymay
charlene
caramelo
selena
lucero
wendy
volcom
1435254
copper
cindy
baby123

地球真危险!稣回月球了……

adduser 和 useradd 的区别

需求

在 armbian 系统里新建个账号。

这当然是个简单的任务,问题是发现居然同时存在 adduser 和 useradd 两个命令。

解决选择恐惧症

  1. adduser 不是可执行程序。
1
2
3
4
5
which adduser
/usr/sbin/adduser

ldd /usr/sbin/adduser
not a dynamic executable
  1. useradd 是可执行程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
which useradd
/usr/sbin/useradd

ldd /usr/sbin/useradd
linux-vdso.so.1 (0xbea59000)
libaudit.so.1 => /lib/arm-linux-gnueabihf/libaudit.so.1 (0xb6ea1000)
libselinux.so.1 => /lib/arm-linux-gnueabihf/libselinux.so.1 (0xb6e77000)
libsemanage.so.1 => /usr/lib/arm-linux-gnueabihf/libsemanage.so.1 (0xb6e3f000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6d45000)
/lib/ld-linux-armhf.so.3 (0xb6efb000)
libcap-ng.so.0 => /lib/arm-linux-gnueabihf/libcap-ng.so.0 (0xb6d31000)
libpcre.so.3 => /lib/arm-linux-gnueabihf/libpcre.so.3 (0xb6cd4000)
libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xb6cc1000)
libsepol.so.1 => /lib/arm-linux-gnueabihf/libsepol.so.1 (0xb6c44000)
libbz2.so.1.0 => /lib/arm-linux-gnueabihf/libbz2.so.1.0 (0xb6c28000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6c03000)
  1. 推测 adduser 是脚本,内部调用 useradd。求证之!
1
2
3
4
5
6
7
8
9
head -1 /usr/sbin/adduser
#!/usr/bin/perl

grep useradd /usr/sbin/adduser
my $useradd = &which('useradd');
&systemcall($useradd, '-d', $home_dir, '-g', $ingroup_name, '-s',
my $useradd = &which('useradd');
&systemcall($useradd, '-d', $home_dir, '-g', $ingroup_name, '-s',
# useradd without -p has left the account disabled (password string is '!')

这说明 adduser 是 perl 脚本,内部确实调用 useradd。

  1. 直觉告诉 UMU,应该用 adduser,如果 useradd 很好用,不会有 adduser 存在的必要。

优化思维【6】安全性

前情

前五篇,主要考虑性能优化,只有第二篇与安全性相关。

其实区块链业界一直不缺乏黑客,最近看过不少安全事故导致惨重代价,所以想总结点安全性方面的优化思路。(本篇比较务虚,只是大体思路。)总的来说,为了安全是必须付出实现或者性能代价的。实现代价是开发、测试阶段就要投入更多精力,性能代价是因为考虑更多,有可能消耗更大运行资源。但从长期来看,这些代价都是必须的。

产品价值与安全意识

开发者可能有能力做一定安全防范,但如果他认为产品没有价值,没必要防范,就可能明明有能力防住,实际却被黑翻车。要不要注重安全性,是设计阶段就应该交代清楚的。

夫兵久而国利者,未之有也。故不能尽知用兵之害者,则不能尽知用兵之利也。——《孙子兵法》

做任何事情先考虑失败。——李嘉诚

程序员版解读:安全怎么能大意,甚至忽视?那都是侥幸心理,只要您的产品、服务有价值,长期看都会被破解、攻击。开发者如果不能知悉黑客可能的攻击点,并衡量被攻破的代价,他必然也不清楚自己写的代码的真正价值。

实际开发过程中,有些领导者会故意隐藏关于产品价值的信息,这实际上可能导致安全考虑不到位。这种情况就应该配备一个在安全方面经验丰富的审查者。

一句话总结:越有价值的东西,就越应该注重安全。

知识深度

一般黑客都是上层、底层皆通,尤其擅长底层。很少听说只做增删查改业务的人能够黑掉什么东西、偷到数字货币,因为同样只做增删查改业务的人就具备防止这种级别的攻击手段。

比如古老的 SQL 注入漏洞,即便是入门级的 Web 开发也能理解并防护,用预编译语句、存储过程、改用 ORM 就天然免疫。他们无法防护的往往来自更底层的 Web Server 的漏洞,比如 Apache、Nginx 某个版本有 bug,刚好中枪。

再举个例子,用 C/C++ 写 UDP 服务程序,“先把它实现,能用就行”,“不就 socket 嘛?很容易!”于是没有考虑 socket 等资源的生存周期,没料到黑客可以伪造 UDP 包源地址,实现出来的就可能有拒绝服务攻击 (Denial of Service,DoS) 漏洞

总之,为了性能或安全的优化,开发者往往需要往底层钻。为性能,主要是研究底层模块与之配合,达到消除瓶颈目的;为安全,则是不让对底层设计的不了解,导致实现不够严谨周密而产生漏洞。

知识广度

经常听到这样的段子:

千万不要跟程序员说,你的代码有 bug。

他的第一反应是你的环境有问题,第二就是你是傻逼不会用吧!

你要跟他这么说:这个程序运行的怎么运行的跟预期不一样,是我操作有问题吗?

这货就会第一反应,我擦,这是不是出 bug 了?

这段子里其实间接反映一个程序员经常遇到的问题:自己测试没问题,一到用户侧或者线上就莫名出问题。环境不同,是最大原因。比如 Linux 的发行版众多;著名的 Android 碎片化;iPhone 型号随时间推移也越来越多了……

另一个大原因则是依赖。比如古老的 DLL Hell。类似的问题在 macOS、Linux 上也都存在。有一次 UMU 把 macOS 的 OpenSSL 升级到 1.1,结果 1.0 居然被删掉,导致原来编译的依赖 1.0 的 eos 就无法运行了。

再以 eos 为例,它依赖不少库,这些依赖库本身也可能有 bug,也要升级。又比如 ipfs,熟悉下来,发现其依赖树很广。作为开发者,引入一个依赖时,肯定需要操心会不会同时引入 bug。一般解决方式是:采用被大量验证的著名库,尽快跟进最新稳定版本。

总之,为了安全,设计者可能需要了解更多方面的知识,并不仅限于表面上需要的那些。开发者还要与时俱进,积极消灭潜在的漏洞。

开发语言

高级语言程序员可能很少听说缓冲区溢出,即使有,多半也是这门语言的宿主、解释器的 bug。而 C/C++ 等能直接操作指针的语言,就可能听到栈溢出、空指针、野指针等。采用高级语言确实会在程序执行时的安全性上省心不少,能把更多精力放在流程安全、业务安全上。

从架构上说,应该让不同语言只用于它擅长的领域。比如用 Rust 实现底层模块,用 Go 实现上层业务。这种分层选择语言的方式,充分利用 Rust 的安全性和底层开发能力,还可以让分工更清晰、沟通更愉快。

为什么 EOS 私钥有不同长度?

问题

这里有两个 EOS 私钥,它们长度居然不一样?

  • PVT_K1_1EEr5aW5162skbocDSMDgoWn9jna6HPSr1TwEMR6PNXbPtRky

  • PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V

为什么私钥有不同长度?而公钥就都是固定长度呢?

知识点

  • 私钥是一个大型随机数,而公钥则是私钥乘以椭圆曲线上的基点后对应的点。对于 secp256k1 来说,是 256 位,并且 < n 的整数。

  • n 须为质数,Order of G,是使得 n * G = 0 的最⼩正整数,n 是安全性最⼤的决定因素。对于 secp256k1 来说,n
    = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141。

  • 不是每个数都安全,比如小的数肯定是不安全的,黑客可以从 1 开始枚举,不够大的数很快就被找到对应关系,也可以从 n 倒着枚举,所以太大的也不安全。(PS:临近一些特别数的数也不安全……)一般来说,私钥的安全范围是 [0x0080000000000000000000000000000000000000000000000000000000000000, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff]。

工具

https://github.com/UMU618/secp256k1-tools

使用 private-2-public.js 可以把私钥转为它代表的数字:

1
2
3
4
5
6
7
8
9
10
11
12
13
DEBUG=* node private-2-public.js PVT_K1_1EEr5aW5162skbocDSMDgoWn9jna6HPSr1TwEMR6PNXbPtRky
secp256k1-tools:key-util pvt = 84ade57e2b35cca8972562fcc6d1f6f2fbf078c4f2cfb532eb4d740767c5a8 +0ms
secp256k1-tools:key-util x = 2110b8d675240f5d548d166cc06b22f44c671d762711a3a67027b74cd166ab76 +9ms
secp256k1-tools:key-util y = 20ac68b75ad8b0e4bc3ec5705ebaf57c69d2d8268504d6aa95fdebfd0b7db831 +0ms
PVT_K1_1EEr5aW5162skbocDSMDgoWn9jna6HPSr1TwEMR6PNXbPtRky
PUB_K1_75o92oRgWSgx3XzTDYPj1e3hFSRhMnKaUdW8ZZpxJXkhfiGBHS

DEBUG=* node private-2-public.js PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V
secp256k1-tools:key-util pvt = d2653ff7cbb2d8ff129ac27ef5781ce68b2558c41a74af1f2ddca635cbeef07d +0ms
secp256k1-tools:key-util x = c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf +8ms
secp256k1-tools:key-util y = eeceff7130fd352c698d2279967e2397f045479940bb4e7fb178fd9212fca8c0 +1ms
PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V
PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63

分析

1. 数值比较

  • PVT_K1_1EEr5aW5162skbocDSMDgoWn9jna6HPSr1TwEMR6PNXbPtRky,有 56 个字符,去掉前缀和校验码后有 45 个字符,它代表 0x84ade57e2b35cca8972562fcc6d1f6f2fbf078c4f2cfb532eb4d740767c5a8;

  • PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V,有 57 个字符,去掉前缀和校验码后有 46 个字符,它代表 d2653ff7cbb2d8ff129ac27ef5781ce68b2558c41a74af1f2ddca635cbeef07d。

可以清楚地看出前者短一个字符,数值也相应比较小。

2. BASE58 编码的原理

BASE58 的字符集:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz,其中 ‘1’ 代表 0,‘z’ 代表 57。把待编码的数字不断除以 58,并将余数用对应的字符表示。举个小点的数字做例子:618

1
2
3
618 / 58 = 10 .. 38 -> f

10 / 58 = 0 .. 10 -> B

拼接余数得 fB,再反转得 Bf。

3. BASE58 编码位数关系

一个数编码后,应该长于或等于比它小的数。我们可以通过简单的数学计算得出 45 个字符的 BASE58 编码可以表示的最大数:

zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = 0xc33ed2d1fbdd3bfe9c22b96164d38cf0d640e1c0ee8b61c39c57899fffffffffff

所以 <= 0xc33ed2d1fbdd3bfe9c22b96164d38cf0d640e1c0ee8b61c39c57899fffffffffff 的私钥编码后是 56 个字符;大于者 59 个字符。

4. 旧格式私钥

  • 旧格式私钥:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

  • 对应新格式:PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V

同理,只是格式不同罢了。不再展开。

5. 为什么公钥是固定长度呢?

因为公钥有个表示奇偶性的前缀,0x02 或者 0x03,所以它的大小范围被限定,没能相差一个 BASE58 字符。

相关文章

基于 ECC 的私钥转为公钥的过程

ECC Node.js

nfs-ganesha 端口绑定

需求

前文《在 Armbian 安装 NFS 服务端》介绍 nfs-ganesha 的安装配置。经过几天使用,发现效果还可以,但一直都是在局域网内使用,突然有一天想在公司访问家里的 NFS 共享……

问题

直接 mount 会一直卡着。

开放 111、2049 端口,再 mount,还是卡着。

通过反复重启 nfs-ganesha 并 netstat -nalp | grep ganesha.nfsd 观测,发现 mountd 端口不固定!给开放端口配置带来困难。

解决

Armbian 配置

将 mountd 端口绑定,比如 2618,但配置的方法和常规 Debian 服务器的内核级 NFS Server 不同。修改 /etc/services 添加 mountd 绑定是无用的,应该编辑 /etc/ganesha/ganesha.conf,添加以下配置:

1
2
3
4
NFS_CORE_PARAM
{
MNT_Port = 2618;
}

改完重启服务:

1
systemctl restart nfs-ganesha.service

防护墙配置

UMU 用的是 OpenWRT 路由器作为家庭网络出口,firewall 配置文件是 /etc/config/firewall,添加以下几行:

1
2
3
4
5
6
7
8
9
10
config rule
option src 'wan'
option name 'Allow-NFS'
option dest '*'
option target 'ACCEPT'
option dest_port '111 2049 2618'
option family 'ipv6'
option start_time '00:09:00'
option stop_time '00:21:00'
option enabled '0'

以上配置开启了 111、2049、2618 三个端口的转发,其中 udp/tcp 111 是 portmap 端口,udp/tcp 2049 是 nfsd 端口,udp/tcp 2618 是上一步绑定的 mountd 端口。

/etc/init.d/firewall restart 重启后就可以在办公室通过 IPv6 访问家里的 NFS 共享了。

参考

https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/config_samples/config.txt

在 Armbian 安装 NFS 服务端

需求

有个刷了 Armbian 的玩客云想当文件共享服务器。

问题

某些版本的 Armbian 内核不支持 nfsd,刚好稣就刷到!如果按照 debian 服务器玩法——安装 kernel 版服务端,是无法正常工作的:

1
apt install nfs-common nfs-kernel-server

启动时会提示:

1
2
3
4
5
6
mount: /proc/fs/nfsd: unknown filesystem type 'nfsd'.
proc-fs-nfsd.mount: Mount process exited, code=exited, status=32/n/a
proc-fs-nfsd.mount: Failed with result 'exit-code'.
nfs-mountd.service: Job nfs-mountd.service/start failed with result 'dependency'.
nfs-idmapd.service: Job nfs-idmapd.service/start failed with result 'dependency'.
nfs-server.service: Job nfs-server.service/start failed with result 'dependency'.

解决

服务端

使用用户态的 nfs-ganesha。

1
apt install nfs-ganesha nfs-ganesha-vfs

配置文件为 /etc/ganesh/ganesha.conf。nfs-ganesha-vfs 包另带一个 vfs.conf 参考模板。以下配置创建读写共享 /root/share 和只读共享 /opt:

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
EXPORT_DEFAULTS
{
Protocols = 4;
}

EXPORT
{
Export_Id = 77;
Protocols = 3, 4;
Path = /root/share;
Pseudo = /root/share;
Access_Type = RW;
FSAL {
Name = VFS;
}
}

EXPORT
{
Export_Id = 78;
Path = /opt;
Pseudo = /opt;
Access_Type = RO;
FSAL {
Name = VFS;
}
}

改完重启服务:

1
systemctl restart nfs-ganesha.service

客户端

  • Debian
1
2
3
4
5
6
7
8
9
sudo apt install nfs-common

showmount -e u1
Export list for u1:
/root/share (everyone)

sudo mkdir /mnt/share
# sudo mount -t nfs u1:/root/share /mnt/share
sudo mount.nfs u1:/root/share /mnt/share

注意:如果提示 mount.nfs: No such device,说明内核没有 NFS 模块,洗洗睡了,换 Windows 10 吧!

  • Windows 10

安装 NFS 客户端

浏览 NFS 共享目录

NFS 属性

注意:Windows 10 目前只有 NFS v3 客户端。服务端如果只开 v4 协议,则 Windows 10 将无法访问。

参考

https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/config_samples/config.txt

https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/config_samples/export.txt

解决通过 TTL 登录 Armbian 时的 Login incorrect

问题

用 TTL 连接刷 Armbian buster 的盒子,然后用 putty 和 plink 登录,一输入 root 回车,就报 Login incorrect!但通过 ssh 远程登录却没任何问题。

原因

ttyAML0 不在 /etc/securetty 里。

分析过程

一开始听运维小伙伴说:最可能的原因是键盘 Caps 开启了。轻松排除。

后来发现输入大写的 ROOT,反而提示输入 password,这让稣想到“枚举用户”攻击。开始思考,是不是通过 TTL 登录被 Armbian 认为是不安全的?

于是学习 securetty 相关知识,发现确实在某些不安全场合 root 是不被允许登录的,因为系统管理员一旦通过不安全渠道输入密码,那么密码就可能被盗取,所以一输入 root,就应该立刻报错,而不该继续让输入密码。而输入其它不存在的用户时(比如大写的 ROOT),反而应该让继续输入密码,最后再提示登录失败,因为如果提示用户不存在,会让黑客穷举出系统里有什么账号。

1
2
3
grep securetty /etc/pam.d/login
# Disallows root logins except on tty's listed in /etc/securetty
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so

后来注意到 TTL 用的 tty 名字是 ttyAML0,grep ttyAML0 /etc/securetty 果然不存在。

解决

echo ttyAML0 >> /etc/securetty 搞定。