linux telnetd 分析
Linux 发行版本视 telnet 为不安全工具,对 telnet 的支持比较差。
目前发行版主要使用 inetd (internet “super-server”) + telnetd 的形式,并没有独立的 telnet 服务器。一般只有在嵌入式系统中才有 telnet standalone 服务器。
- telnetd, 源码隶属 netkit-telnet
- xinetd + telnetd
- openbsd-inetd + tcpd + telnetd
- standalone telnetd:
- utelnetd, https://wiki.gentoo.org/wiki/Utelnetd, 代码https://public.pengutronix.de/software/utelnetd/, 用于 optware/gentoo 等。
- busybox telnetd
优缺点分析:
- inetd + telnetd
- 目前各大发行版本支持
- 正常情况下,可直接安装使用。目前在 ubuntu 上验证,即装即可用,但是在 debian jessie 上,不可用。下文详细介绍 fix 过程,fix 后 openbsd-inetd (debian 默认 inetd) + telnetd 可用。
- 不方便维护,除 telnetd,还需要引进 inetd,多一个故障点
- 多一个 inetd,多一个代码维护点
- standalone telnetd
- 代码少,以 utelnetd 来讲,空行算进去,总的也才 600 多行。
- 相比 inetd + telnetd 方式,部署简单,方便维护。
- busybox 的 telnetd 在整个 busybox 框架下,如果单独剥离出来,需要一定工作量。相比之下,utelnetd 很方便。
关于 inetd
网上推荐使用 xinetd,redhat 系用 xinetd 比较多。debian 系支持的比较少,像 update-inetd 就明确安装时就说明不完全支持 xinetd。
inetd listens for connections on certain internet sockets. When a connection is found on one of its sockets, it decides what service the socket corresponds to, and invokes a program to service the request. After the program is finished, it continues to listen on the socket (except in some cases which will be described below). Essentially, inetd allows running one daemon to invoke several others, reducing load on the system.
utelnetd 验证
验证可用。
验证 log:
1 | a@xxx:~$ sudo lsof -i:23 -n |
编译记录
1 | jeromesun@km:~/workshop$ tar xvf utelnetd-0.1.11.tar.gz |
openbsd-inetd + telnetd 验证
在 debian jessie 上验证。
虽然不用,但是存档。
问题分析
问题现象:telnet 客户端在几秒钟后自行退出。
1 | [20181026-091148.403]a@xxx:~$ telnet localhost |
log 分析:
1 | Oct 26 18:17:42 xxx in.telnetd[4140]: connect from 127.0.0.1 (127.0.0.1) |
下载 telnetd 源码,grep 并没有发现文件有 cannot execute
的字样。
进一步下载 tcp-wrapper 和 openbsd-inetd 源码,发现该 log 在 tcp-wrappers/tcpd.c
中。应该是入参有问题,
1 | ... |
改下代码,把所有的 argv 打出来:
1 | Oct 26 18:17:42 xxx in.telnetd[4140]: argc 0 |
发现入参是 in.telnetd,不是 /etc/inetd.conf
中写的 /usr/sbin/in.telnetd
。
1 | telnet stream tcp nowait telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd |
有点奇怪:
- openbsd-inetd 执行 telnet 服务时,执行的是什么命令
- 即使 openbsd-inetd 执行时,以 in.telnetd 直接传入,
REAL_DAEMON_DIR
在编译时也有定义,应该有值才对。
1 | cc -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -DFACILITY=LOG_DAEMON -DHOSTS_ACCESS -DNETGROUP -DDAEMON_UMASK=022 -DREAL_DAEMON_DIR=\"/usr/sbin\" -DPROCESS_OPTIONS -DACLEXEC -DKILL_IP_OPTIONS -DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 -DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" -DSYS_ERRLIST_DEFINED -DHAVE_STRERROR -DHAVE_WEAKSYMS -DINET6=1 -Dss_family=__ss_family -Dss_len=__ss_len -o tcpd.o -c tcpd.c |
先不管了,直接改 tcpd.c 的代码,将所有 telnet 服务的入参强制变成 /usr/sbin/in.telnet:
1 | --- <unnamed> |
修改后正常:
1 | [20181026-142113.815][jeromesun@64 ~]$ telnet 192.168.3.31 |
编译记录
在源码根目录,执行 dpkg-buildpackage -rfakeroot -b -us -uc -nc --as-root -Tbinary
进行编译。
1 | jeromesun@km:~/tcp-wrappers-7.6.q$ rm tcpd |
xinetd + telnetd
在 debian jessie 上验证。未成功。