OpenSSH 的一个主要功能是访问并在其他系统上运行程序。

毕竟,这就是该程序的一个主要用途。有几种方法可以扩展这一功能,无论是交互式操作还是作为无人值守脚本的一部分。因此,除了交互式登录外,ssh(1) 还可以用来简单地执行程序或脚本。程序或脚本执行完毕后,自动退出。有些组合非常直观,其他的则需要更多的计划。有时,仅仅知道某个操作是可行的就是一个线索,而有时则需要更多的细节。以下是一些使用 OpenSSH 运行远程任务的有用示例。

运行远程进程

ssh(1) 的一个显而易见的用途是运行远程系统上的程序并退出。通常这是一个 shell,但它可以是帐户可用的任何程序。为了获取反馈,ssh(1) 会传回远程进程的退出值。当远程进程完成时,ssh(1) 将终止并返回最后一个完成的远程进程的退出值。通过这种方式,它可以用于脚本中,并且远程进程的结果可以被客户端系统使用。

以下命令将在远程系统上运行 true(1) 并将成功(退出码为 0)返回到运行 ssh(1) 的本地系统。

$ ssh -l fred server.example.org /bin/true
$ echo $?
0

以下命令将在远程系统上运行 false(1) 并将失败(退出码为 1)返回到运行 ssh(1) 的本地系统。

$ ssh -l fred server.example.org /bin/false
$ echo $?
1

如果返回了其他值(从 0 到 255),ssh(1) 会将这些值从远程主机传回本地主机。

运行远程进程并在本地捕获输出

可以使用普通的重定向将远程计算机上运行的程序的输出保存到本地。以下命令在远程计算机上运行 dmesg(8)

$ ssh -l fred server.example.org dmesg > dmesg.from.server.log

交互式进程会很难或不可能以这种方式操作,因为看不到输出。对于需要任何用户输入的交互式进程,输出可以通过 tee(1) 管道传送,从而将输出同时发送到文件和标准输出。以下示例远程运行一个匿名 FTP 会话,并将输出记录到本地:

$ ssh -l fred server.example.org "ftp -a anotherserver" | tee ftp.log

有时,可能需要强制分配伪终端(pseudo-TTY)以确保输入和输出能够正确显示。

$ ssh -t -l fred server.example.org "ftp -a anotherserver" | tee /home/fred/ftp.log

在一台计算机上读取数据并在另一台计算机上处理数据的最简单方法是使用管道。

$ ssh fred@server.example.org 'cat /etc/ntpd.conf' | diff /etc/ntpd.conf -

运行本地进程并捕获远程数据

数据可以在一台系统上生成并在另一台系统上使用。这与 X 隧道不同,在 X 隧道中,程序和数据都驻留在另一台计算机上,只有图形界面在本地显示。再次强调,读取一台计算机上的数据并在另一台计算机上使用它的最简单方法是使用管道。

$ cat /etc/ntpd.conf | ssh fred@server.example.org 'diff /etc/ntpd.conf -'

如果本地程序期望从远程计算机读取文件,可以使用命名管道配合重定向来传输数据。在以下示例中,创建了一个命名管道作为数据的传输点。然后,使用 ssh(1) 启动远程进程,将输出发送到标准输出,输出通过本地计算机的重定向捕获,并发送到命名管道,以便本地程序通过该管道访问数据。

在这个特定示例中,重要的是在 tcpdump(8) 本身中添加一个过滤规则,以防止当 ssh(1) 通过与数据收集相同的接口连接时发生无限反馈循环。此循环通过排除 SSH 端口、SSH 连接使用的主机或相应的网络接口来防止。

$ mkfifo -m 600 netdata

$ ssh -fq -i /home/fred/.ssh/key_rsa \
        'sudo tcpdump -lqi eth0 -w - "not port 22"' > netdata

$ wireshark -k -i netdata &

tcpdump(8) 的任何 sudo(8) 权限还需要在没有交互密码的情况下运行,因此必须非常小心地在 /etc/sudoers 文件中精确地列出允许哪些程序和参数,而不允许其他任何操作。ssh(1) 的身份验证也必须以非交互方式进行,例如通过密钥和密钥代理。一旦配置完成,ssh(1) 会在连接后运行并进入后台。通过后台运行的 ssh(1),本地应用程序(此例中为 wireshark(1),一个图形化网络分析器)会启动,并设置为读取命名管道作为输入。

在某些系统上,进程替代可以简化两台计算机之间的数据传输。使用进程替代只需一行命令。

$ wireshark -k -i <( ssh -fq -i /home/fred/.ssh/key_rsa \
        'sudo tcpdump -lqi eth0 -w - "not port 22"' )

然而,进程替代不符合 POSIX 标准,因此在不同平台之间不可移植。它仅限于 bash(1),其他 shell 中并不存在。因此,为了可移植性,建议使用命名管道。

运行远程进程,无论是否连接

有几种不同的方法可以让进程在远程计算机上继续运行。如果目的是定期回到进程并检查其状态,那么终端多路复用器可能是最好的选择。对于更简单的需求,还有其他方法可以实现。

在断开连接时后台运行远程进程

许多常规任务可以启动后让它们自行完成,而无需保持登录状态。当远程进程在后台运行时,通常需要为该任务启动一个 shell。

$ ssh -t -l fred server.example.org 'sh -c "tar zcf /backup/usr.tgz /usr/" &'

另一种方法是使用终端多路复用器。使用终端多路复用器的一个优势是能够重新连接并时不时查看进度,或者在连接被中断(例如旅行时)后恢复工作。在这里,tmux(1) 会重新附加到现有会话,如果没有会话,则创建一个新的会话。

$ ssh -t -l fred server.example.org "tmux a -d || tmux"

在较旧的系统上,screen(1) 通常可用。在这里,远程启动 screen(1),如果没有现有会话,则创建一个新的会话,或者如果已经有会话在运行,则重新附加到该会话。因此,如果没有运行中的 screen(1) 会话,将会创建一个新的会话。

$ ssh -t -l fred server.example.org "screen -d -R"

一旦 screen(1) 会话启动,就可以将其分离,并关闭 SSH 连接,而不会打扰它可能在后台运行的进程。这对于在远程机器上托管某些游戏服务器时特别有用。然后,终端会话可以继续被附加并恢复工作,使用相同的两个选项。

$ ssh -t -l fred server.example.org "screen -d -R"

关于使用终端多路复用器 tmux(1)screen(1) 的更多内容见下文。在某些环境中,可能还需要使用 pagsh(1),特别是在 Kerberos 环境下,见下文。另外,nohup(1) 也可能会派上用场。

断开连接后保持远程进程的认证票据

在注销时,认证凭证通常会被删除,因此任何剩余的进程将无法访问这些凭证所使用的认证令牌。在这种情况下,需要先创建一个新的凭证缓存沙箱,以便在断开连接前运行独立的进程。

$ pagsh
$ /usr/local/bin/a-slow-script.sh

Kerberos 和 AFS 是需要有效、活动票据的两个例子。使用 pagsh(1) 是这些环境中的一种解决方案。

使用 tmux(1) 或 screen(1) 自动重新连接并恢复 SSH 会话

可以使用终端多路复用器恢复主动的、正在运行的会话,无论是因故意还是意外中断。这里的 ssh(1) 假设在 15 秒(每次尝试 5 秒,共 3 次)无法连接服务器后,连接断开并退出。然后,tmux(1) 会话会被重新附加,如果不存在会话,则创建一个新的会话。

$ while ! ssh -t fred@example.org -o 'ServerAliveInterval 5' \
	'tmux attach -d || tmux new-session'; \
  do true; \
  done

每次 ssh(1) 退出时,shell 会尝试重新连接,并在成功连接后查找一个 tmux(1) 会话以附加。如果 TCP 或 SSH 连接中断,终端多路复用器内的应用程序或会话将继续运行。以下是较旧系统上 screen(1) 的示例。

$ while ! ssh -t fred@example.org -o 'ServerAliveInterval 5' \
	'screen -d -R'; \
  do true; \
  done

以上示例仅提供了一个过于简单的演示,基本上它们用于恢复在 TCP 连接断开后 shell 的状态。tmux(1)screen(1) 功能强大,值得进一步探索,特别适合旅行者和远程工作人员。

另见“公钥认证”部分,将密钥集成到自动重新连接的过程中。

共享远程 Shell

在教学、团队编程、监督和创建文档等场景中,两个用户共享一个 shell 可能会非常有用。这里有几种只读查看以及允许多个用户读取和写入的选项。

只读监控或日志记录

管道和重定向是快速保存 SSH 会话输出或允许其他用户只读跟踪的好方法。

一个示例用例是,当路由器需要重新配置并且通过串行控制台可用时。假设路由器出现故障,顾问必须通过另一个用户的笔记本连接登录以访问路由器的串行控制台,并且必须监督或在某些阶段提供帮助。这在记录各种活动(包括配置或安装)时也非常有用。

使用 tee(1) 只读

将 shell 活动捕获到日志文件,并可选择使用 tail 实时查看。tee(1) 工具像管道中的 T 接头一样,用于将输出同时发送到两个目标:标准输出和文件。

$ ssh fred@server.example.org | tee /tmp/session.log

生成的文件可以在另一个终端中使用 tail(1) 实时监控,或使用 less(1) 等分页工具查看。

强制串行会话并使用 tee(1) 进行远程日志记录

tee(1) 工具可以捕获任何可以写入标准输出的程序的输出。这对于远程现场帮助、监督或构建文档非常有用。

这个示例使用 chroot(8) 来尽可能限制可选操作。实际上构建 chroot 监狱是一个单独的任务。一旦构建完成,访客用户将被添加到 consult 组中。测试的串行连接在设备 ttyUSB0 上,这是一个 USB 到串行转换器,使用 cu(1) 进行连接。tee(1)cu(1) 的输出捕获并保存到日志文件中。以下内容应添加到 sshd_config(5) 文件中:

Match Group consult
        ChrootDirectory /var/chroot-test
        AllowTCPForwarding no
        X11Forwarding no
        ForceCommand cu -s 19200 -l /dev/ttyUSB0 | tee /var/tmp/cu.log

通过这种方式,一个或多个人可以通过 tail(1) 跟踪 cu(1) 中的活动,并将其指向远程服务器上的日志文件。

$ tail -f /var/tmp/cu.log

日志可以编辑并用作文档,也可以让 tmux(1)screen(1) 的高级用户允许只读观察者。

脚本编写

可以自动化某些连接操作。制作一个脚本,例如 /usr/local/bin/screeners,然后使用该脚本与 ForceCommand 指令一起使用。以下是一个脚本示例,尝试重新连接到一个现有的会话。如果没有现有会话,则创建一个新的会话并自动建立与串行设备的连接。

#!/bin/sh

# 尝试附加到一个已存在的 screen 会话,
# 如果没有,则创建一个新的 screen 会话

/usr/bin/screen -d -R || \
        /usr/bin/screen \
            /bin/sh -c "/usr/bin/cu -s 19200 -l /dev/ttyUSB0 | \
            /usr/bin/tee /tmp/consultant.log"

使用终端多路复用器进行交互式共享

终端多路复用器(如 tmux(1)screen(1))可以让两个或更多人共享同一个会话。[1] 会话可以设置为某些用户只读,或让所有参与者都能读写。

tmux(1)

如果是同一个账户共享会话,操作相对简单。在第一个终端中启动 tmux(1),其中 sessionname 是会话名称:

$ tmux new-session -s sessionname

然后在第二个终端中:

$ tmux attach-session -t sessionname

如果是同一个账户从不同位置登录并共享会话,则只需要这些操作。如果是不同的用户共享会话,则需要设置 tmux(1) 套接字的权限,以便两个用户都可以读写。首先,需要一个包含两个用户的共享组。

在两个账户都加入共享组后,在第一个终端(即主账户所在的终端)中,启动 tmux(1),并为会话的套接字指定一个名称。这里 sessionname 是会话名称,sharedsocket 是套接字的名称:

$ tmux -S /tmp/shareddir/sharedsocket new-session -s sessionname

接下来,改变套接字及其目录的组,使两个用户共享相同的组,并确保套接字权限允许该组写入套接字。在这个示例中,共享组是 foo,套接字是 /tmp/shareddir/sharedsocket

$ chgrp foo /tmp/shareddir/
$ chgrp foo /tmp/shareddir/sharedsocket
$ chmod u=rwx,g=rx,o= /tmp/shareddir/
$ chmod u=rw,g=rw,o=  /tmp/shareddir/sharedsocket

最后,让第二个账户登录并使用共享套接字附加到指定会话。

$ tmux -S /tmp/shareddir/sharedsocket attach-session -t sessionname

此时,任一账户都可以读写同一个会话。

screen(1)

如果是同一个账户共享 screen(1) 会话,则过程很简单。在一个终端中,启动一个新会话并为其指定名称。在此示例中,sessionname 是会话名称:

$ screen -S sessionname

在另一个终端中,附加到该会话:

$ screen -x sessionname

如果是两个不同账户共享同一个 screen(1) 会话,则需要额外的步骤。第一个用户在启动会话时执行以下操作:

$ screen -S sessionname
^A :multiuser on
^A :acladd user2

然后第二个用户执行:

$ screen -x user1/sessionname

screen(1) 中,如果使用多个用户账户,可以使用 aclchg 命令为其他用户移除写权限:^A :aclchg user -w "#". 请注意,screen(1) 必须以 SUID 运行以支持多用户。如果未设置该权限,连接第二个用户时会出现错误消息提醒。您可能还需要为 /var/run/screen 设置 755 权限。

使用 X11 转发在本地显示远程图形程序

可以在远程机器上运行图形程序,并通过转发 X11(即 X 窗口系统的当前实现)在本地显示。X11 用于在许多系统上提供图形界面。有关 X11 的历史和技术细节,请访问 www.X.org 网站。它已被集成到大多数桌面操作系统中,甚至作为 macOS 的一部分,尽管它不是默认的图形显示方法。

X11 转发默认是关闭的,必须在 SSH 客户端和服务器上都启用才能使用。

X11 还使用客户端-服务器架构,X 服务器是负责为最终用户实际显示的部分,而各种程序作为客户端与服务器进行通信。因此,通过将客户端和服务器放置在不同的机器上并转发 X11 连接,可以在其他计算机上运行程序,但它们将以在用户计算机上运行的方式显示并可用。

需要注意的是,允许远程机器转发 X11 连接将使其及其应用程序能够访问托管 X 服务器的机器上的许多设备和资源。无论用户的意图如何,这些设备和资源都是用户账户可访问的。因此,只有在远程机器、用户账户及其应用程序可靠时,才应启用转发。

服务器端启用 X11 转发

在服务器端,要启用 X11 转发,可以在 sshd_config(5) 文件中添加以下行,可以放在主配置块或 Match 配置块中:

X11Forwarding yes

客户端启用 X11 转发

客户端默认关闭 X11 转发,但可以通过三种方式启用。可以在 ssh_config(5) 中启用,也可以通过使用 -X-Y 运行时参数来启用。

$ ssh -l fred -X desk.example.org

然而,连接可能会比较慢。如果响应速度是一个关键因素,可能需要考虑使用 SOCKS 代理,或者使用一些其他技术,比如 FreeNX。

使用 ssh_config(5) 指定 X11 转发

X11 转发可以在 /etc/ssh_config 中为所有账户的所有外出 SSH 连接启用,或者仅为特定主机配置 ssh_config(5)

X11Forwarding yes

也可以将 ssh_config(5) 设置应用于特定账户,限制默认的转发仅对特定主机(按主机名或 IP 地址)启用。在 ~/.ssh/config 中,以下是为特定主机启用 X11 转发的配置:

Host desk.example.org 
        X11Forwarding yes

通过 IP 地址启用特定机器的 X11 转发:

Host 192.168.111.25 
        X11Forwarding yes

同样,可以使用限制模式匹配允许为子域或一段 IP 地址范围启用转发。以下是为 pool.example.org 域中的任何主机、从 192.168.100.100192.168.100.109 的任何主机,以及从 192.168.123.1192.168.123.254 的任何主机启用 X11 转发的配置:

Host *.pool.example.org 
        X11Forwarding yes

Host 192.168.100.10?
        X11Forwarding yes

Host 192.168.123.*
        X11Forwarding yes

X11 是大多数桌面系统内置的。对于 macOS,有一个可选的插件,它的根源在于 NextStep。然而,一些特别过时的遗留平台可能缺少 X11 支持,但即便在这些平台上,通常也可以通过使用合适的工具进行改造,例如使用 Xming 工具。

无特权的 sshd(8) 服务

可以使用无特权账户在高端口上运行 sshd(8)。由于它无法创建其他账户的会话,因此只能在运行无特权服务的账户上进行登录。

运行无特权 SSH 服务的一般步骤如下:

  1. 在启动 SSH 守护进程之前,需要为无特权账户创建一些无特权主机密钥。这些密钥用于标识此服务,尤其是在再次连接时。每个账户只需要创建一次这些密钥,并且密钥的密码短语必须留空。
$ ssh-keygen -q -t ed25519 -N '' \
        -f /home/fred/.ssh/ssh_host_key_ed25519 \
        -C '无特权的 SSH 主机密钥'

如果需要,也可以为 ECDSA 和 RSA 密钥做同样的操作。请确保权限正确。密钥所在的目录及其父目录不应对其他账户可写,并且私有 SSH 主机密钥本身必须不可被其他账户读取。

  1. 密钥准备好后,可以通过手动启动 SSH 服务器来测试它们。可以使用 -h 选项指定这些备用的主机密钥文件。请注意,由于账户是无特权的,因此只能使用端口 1024 以上的端口,本例中使用 -p 选项设置端口 2222。
$ /usr/sbin/sshd -D \
        -h /home/fred/.ssh/ssh_host_key_ed25519 \
        -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222

确保从其他系统可以访问新的服务。特别要确保任何可能的包过滤器(如果有)已设置为通过正确的端口。正常使用时,传入连接和任何包过滤器需要考虑到替代端口。另一种方法是将无特权 SSH 服务添加为洋葱服务(onion service)。有关详细信息,请参见关于代理和跳板主机的章节。

启用特定配置文件

请注意,以上示例使用的是守护进程的默认配置文件。如果需要使用其他配置文件来设置特殊的配置,可以在命令中添加 -f 选项。

$ /usr/sbin/sshd -D -f /home/fred/.ssh/sshd_config

可以通过使用替代的配置文件为无特权账户设置特定的配置指令。在该文件中,可以为无特权主机密钥指定位置,并设置替代的监听端口及其他自定义设置。如果需要,还可以通过修改 SyslogFacility 指令,将无特权服务的日志与系统上其他 SSH 服务的日志分开。

自动化启动

如果需要自动化启动过程,可以使用 -D 选项,该选项会保持进程不脱离当前会话并成为守护进程。虽然在测试时这可能非常有用,但在实际使用中可能并非最佳做法,这取决于进程启动的方式。

无特权 sshd(8) 进程的表现

由于使用了无特权账户,特权分离不会发生,所有的子进程将在与原始 sshd(8) 进程相同的账户中运行。以下是一个使用无特权账户并监听 2222 端口的示例,使用了默认配置文件并进行了一些覆盖设置:

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 0 of 10-100 startups

当有人连接但尚未完成登录时,输出可能如下所示。一个监视进程被分叉出来,尽管它被标记为 [priv],但它仍然是无特权进程,并且与父进程处于同一无特权账户下。该监视进程会进一步分叉出一个子进程来管理身份验证:

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 1 of 10-100 startups
fred     1998149 sshd: fred [priv]
fred     1998150 sshd: fred [net]

登录成功后,原来的无特权进程会被丢弃,一个新的无特权进程会被启动来管理交互式会话:

$ pgrep -d , sshd | COLUMNS=200 xargs ps -w -o user,pid,args -p
USER         PID COMMAND
fred     1997992 sshd: /usr/sbin/sshd -h /home/fred/.ssh/ssh_host_key_ed25519 -h /home/fred/.ssh/ssh_host_key_ecdsa -p 2222 [listener] 0 of 10-100 startups
fred     1998149 sshd: fred [priv]
fred     1998410 sshd: fred@pts/20

上述中,进程 1998410 正在管理交互式会话。

锁定受限 Shell

受限 Shell 设置了比标准交互式 shell 更加受控的环境。尽管它的行为几乎与标准 shell 相同,但它对某些功能设置了许多限制,只有允许的功能被启用,其他的都被禁用。以下是一些常见的限制:

  • 无法更改 SHELLENVPATH 变量。
  • 不能使用绝对路径或相对路径运行程序。
  • 不能使用重定向创建文件(特别是 >, >|, >>, <>)。

常见的高级 Shell,如 bash(1)ksh(1)zsh(1) 都可以在受限模式下启动。具体如何启动受限模式,请参考各个 Shell 的手册页面。

尽管有这些限制,仍然有几种方法可以轻松逃脱受限 shell:如果系统路径中有正常的 Shell,它们可以被启动;如果路径中的常规程序提供 shell 跳转到完全的 Shell,也可以使用这些程序;最后,如果 sshd(8) 被配置为允许独立于 shell 运行任意程序,也可以启动完全的 Shell。因此,单纯通过将账户的 shell 设置为 /bin/rbash 来实现受限 Shell 并不足够,还需要采取其他措施来尽可能增加逃逸的难度,尤其是在通过 SSH 连接时。

(以下步骤假设你熟悉相关的系统管理工具及其使用方法,具体的工具选择和使用不在此覆盖。)

首先,创建一个目录,包含一些指向白名单程序的符号链接。这些符号链接指向账户在添加到 PATH 环境变量时应该能够运行的程序。应该确保这些程序没有 shell 跳转能力,并且显然,它们本身不应是没有限制的 Shell。

如果想要防止对整个系统的探索,记得还要将用户锁定到 chroot 或监狱环境中。即使没有像 ls(1)cat(1) 这样的程序,也仍然可以进行一定程度的探索(见下文:“没有 ls(1)cat(1) 时如何探索”)。

使用符号链接

使用符号链接是因为原始文件通常由包管理软件维护,应该不会被移动。如果原始文件和白名单目录位于不同的文件系统中,则无法使用硬链接。如果设置了 chroot 或监狱环境,并且排除了原始文件,则必须使用硬链接。

$ ls -l /usr/local/rbin/
total 8
lrwxr-xr-x  1 root  wheel    22 Jan 17 23:08 angband -> /usr/local/bin/angband
lrwxr-xr-x  1 root  wheel     9 Jan 17 23:08 date -> /bin/date
-rwxr-xr-x  1 root  wheel  2370 Jan 17 23:18 help
lrwxr-xr-x  1 root  wheel    12 Jan 17 23:07 man -> /usr/bin/man
lrwxr-xr-x  1 root  wheel    13 Jan 17 23:09 more -> /usr/bin/more
lrwxr-xr-x  1 root  wheel    28 Jan 17 23:09 nethack -> /usr/local/bin/nethack-3.4.3
...

创建最小的 .profile 文件

接下来,为该账户创建一个最小的 .profile 文件,并将其所有者设置为 root。对父目录(即用户的主目录)也做相同设置。然后,允许该账户所在组对该文件和目录具有读取权限。

$ cd /home/fred

$ cat .profile
PATH=/usr/games:/usr/local/rbin
export PATH HOME TERM

$ ls -ld . .profile
drwxr-xr-x  3 root  fred    512 Jan 17 23:20 .
-rw-r--r--  1 root  fred     48 Jan 17 23:20 .profile

创建并管理账户组

接下来,创建一个用于锁定账户的组,并将该账户加入其中。在此示例中,账户属于 games 组,并将通过该组的成员资格进行限制。

$ groups fred
fred games

锁定 SSH 访问

使用 ForceCommand 指令在服务器配置中锁定该组或账户的 SSH 访问,并将其应用于所选的组。这是为了防止通过 SSH 客户端直接调用 shell(例如通过 ssh -t fred@server.example.org /bin/sh)来轻松绕过限制。记得禁用不需要的转发功能。以下示例展示了如何在 sshd_config(5) 中追加设置,使得 games 组中的任何账户都无论如何都会得到一个受限 shell。

Match Group games
        X11Forwarding no
        AllowTcpForwarding no
        ForceCommand rksh -l

请注意,ForceCommand 通过 -l 选项调用受限 shell,这样它将作为登录 shell 启动,并在存在且可读取的情况下读取和执行 /etc/profile$HOME/.profile 的内容。这是设置自定义 PATH 环境变量所必需的。同样,确保 $HOME/.profile 不能被受限账户编辑或覆盖。还要注意,这将禁用该账户的 SFTP 访问,防止其他潜在的恶意行为。

设置账户的登录 shell

最后,将该账户的登录 shell 设置为受限 shell,并包括其完整路径。可能还需要将该 shell 添加到 /etc/shells 的允许列表中。

警惕:如何在没有 ls(1)cat(1) 的情况下进行探索

以下是一些在受限环境中仍然可以进行探索的方法:

  • 查看当前工作目录中的文件列表:
$ echo *
  • 查看文本文件的内容:
$ while IFS= read -r j; do echo "$j"; done < .profile
Last modified: Sunday, 19 January 2025, 9:45 PM