OpenSSH主机认证(Host-based Authentication)配置方法

本文介绍如何配置SSH主机认证,使管理节点上的用户能无密码登录其他机器。涉及配置文件包括ssh_known_hosts、sshd_config、ssh_config及hosts.equiv。

From: http://blog.jianingy.com/node/82

主机认证的设置上并不复杂,考虑全面就能很容易搞定。我们还是先来简单描述下环境。这里我们假设主机admin是管理节点,我们的目标是admin上的所有用户都能通过主机认证从admin节点上登陆其他机器而不需要输入密码。首先,来看看需要修改的文件有那些以及他们各自的作用。

  • admin上的/etc/ssh/ssh_known_hosts: 系统级别的主机公钥文件,需要将你想登陆主机的公钥全部放在这个文件里。
  • 其他机器上的 /etc/ssh/sshd_config :ssh服务进程的配置文件,稍后我们要在这个文件里开启服务进程对主机认证的支持。
  • admin上的 /etc/ssh/ssh_config: 系统级别的ssh客户端配置文件,我们需要在里面打开客户端对主机认证的支持。
  • 其他机器上的 /etc/hosts.equiv : 允许通过主机认证登陆本机的主机名称(域名或者IP)以及用户名称。(有点拗口,但是就是这个逻辑)

我们先来配置admin上的/etc/ssh/ssh_known_hosts。该文件应该包含admin希望登陆的所有机器的rsa或者dsa公钥。为了获取这个公钥我们可以使用openssh提供的工具“ssh-keyscan”:http://www.linuxmanpages.com/man1/ssh-keyscan.1.php 。下面的例子演示了如何获得几个机器的rsa公钥。

ssh-keyscan -t rsa ls101 ls102 ls103 #获取几个机器的公钥,并输出在屏幕上
 sort <(ssh-keyscan -t rsa ls101 ls102 ls103) <(cat /etc/ssh/ssh_known_hosts) | uniq #获取几个机器的公钥并和原有的公钥列表做简单排重

接下来我们要在其他机器上开启ssh服务进程对主机认证的支持。编辑文件/etc/ssh/sshd_config,进行下面的设置:

HostbasedAuthentication yes #开启主机认证
IgnoreRhosts no # 允许用户自己设置 ~/.shosts 和 ~/.rhosts。该设置对主机认证中root用户的登陆有关键作用。

修改好ssh服务进程的配置文件后,我们需要重新启动一下ssh服务以应用最新的设置。

在各个ssh服务器准备完毕后,我们来配置admin上面ssh客户端参数。编辑文件/etc/ssh/ssh_config,进行下面的设置:

Host *
    HostbasedAuthentication yes # 开启主机认证
    EnableSSHKeysign yes # 开启SSH签名支持

由于主机认证会用到一个叫“ssh-keysign”:http://www.linuxmanpages.com/man8/ssh-keysign.8.php 的程序来进行认证,因此在ssh_config中开启对SSHKeysign的支持是必要的。

最后,我们将admin的域名加入到每个机器的 /etc/hosts.equiv 文件中。现在,在admin上除root用户外的所有用户都可以通过主机认证登陆其他机器了。为了让root用户也有这样的便利,我们还需要在其他机器的/root中加入文件.shosts。其内容和/etc/hosts.equiv相同。至此,我们已经成功完成了ssh主机认证的全部配置。

<think>We are discussing how to interact with the host machine from within a Docker container, specifically when using Docker Desktop. The user wants to know how to execute commands on the host machine from inside a Docker container. Important note: By default, Docker containers are isolated from the host for security. However, there are ways to achieve this interaction. Common methods: 1. Using the `host.docker.internal` DNS name to connect to host services (available in Docker Desktop for Mac/Windows). 2. On Linux, using `--network=host` to share the host's network stack (but note that Docker Desktop runs on a VM on Mac/Windows, so this is different). 3. Mounting the host's filesystem (or parts of it) and then executing commands via a shared script or by invoking a shell on the host from the container? But note: Executing a command on the host from inside the container is not straightforward because the container runs in a separate environment. However, the typical way to run a command on the host is by having a service on the host that accepts commands (e.g., SSH). But that requires setup. Alternatively, if the user is using Docker Desktop, they can use the `host.docker.internal` to connect to the host's network services. But note: Docker Desktop's `host.docker.internal` does not allow arbitrary command execution on the host. It only allows network access. How to execute commands on the host? - One common method is to set up an SSH server on the host and then use an SSH client inside the container to run commands. - Another method is to use a socket mounted into the container (like the Docker socket) to control the host's Docker daemon, which then can run containers on the host or execute commands? But note: Mounting the Docker socket allows the container to control the Docker daemon on the host, which can be used to run a container on the host that executes a command. However, this is a security risk. Step-by-step for SSH method: 1. On the host, ensure SSH server is running (and note the IP and port, but for Docker Desktop use `host.docker.internal` as the hostname). 2. From inside the container, you can use an SSH client to connect to the host. Example: In the container, you can install the SSH client and then run: ssh user@host.docker.internal 'command' However, this requires setting up SSH keys for password-less login or handling passwords. Step-by-step for Docker socket method (if the host is running Docker and the container has the socket mounted): Mount the Docker socket: `-v /var/run/docker.sock:/var/run/docker.sock` Then, inside the container, you can use the Docker CLI to run a container on the host that runs the command. Example command inside the container: docker run --rm -v /:/host alpine chroot /host sh -c "command" But note: This runs a container on the host that is chrooted into the host's filesystem and then runs the command. However, the user is using Docker Desktop, and the host is either Mac, Windows, or Linux? The method may vary. Important: On macOS and Windows, Docker runs in a VM. The `host.docker.internal` refers to the host machine (the Mac or Windows PC) but not the VM. So if we mount the Docker socket, it is the socket of the Docker daemon inside the VM, not the host machine. To execute a command on the actual host (the Mac or Windows machine) from inside a container in Docker Desktop, we have to overcome two layers: container -> VM (the Docker host) -> host machine (the physical machine). There is an experimental feature in Docker Desktop that allows access to the host's services via `host.docker.internal`. But for executing commands, we must set up a way for the VM to run commands on the host. This is complex and not typical. The usual practice is to run the necessary services on the host and expose them via network. Considering the complexity and security, the SSH method is the most straightforward if set up on the host. Steps for Docker Desktop (Mac/Windows) to run a command on the host via SSH: 1. On the host (Mac or Windows PC), enable SSH server and make sure it's running and accessible from the Docker VM? But note: The Docker containers can connect to the host via `host.docker.internal` on the special DNS. 2. Configure SSH server to accept connections (from the container) and set up key-based authentication. 3. In the container, install SSH client and connect to `host.docker.internal` on port 22 (or the configured port). Example: apk add openssh-client # for Alpine ssh -o StrictHostKeyChecking=no -i /path/to/private_key user@host.docker.internal 'ls /' But note: The `host.docker.internal` resolves to the host's IP from the container. However, the SSH server must be running on the host and the host's firewall must allow the connection. Alternatively, for development purposes, we might avoid executing commands on the host and instead design the application to not require it. Given the complexity and security implications, we should also warn the user. Therefore, the answer should: - Explain the challenge and the two common methods (SSH and Docker socket). - Note that for Docker Desktop, the host is the Mac/Windows machine, and the `host.docker.internal` can be used for SSH but requires the host to run an SSH server. - Provide a step-by-step example for the SSH method. Let's write the answer accordingly. </think>### 在 Docker Desktop 中与宿主机交互并执行命令的方法 #### 📌 核心原理 在 Docker 容器中直接操作宿主机需要特殊配置,因为容器默认采用隔离环境。Docker Desktop 通过 `host.docker.internal` 提供宿主机访问能力,该 DNS 名称指向宿主机 IP(支持 macOS/Windows/Linux)[^1]。以下是三种主要交互方式: --- ### 🔧 方法 1:通过 SSH 连接宿主机(推荐) #### 步骤: 1. **宿主机开启 SSH 服务** ```bash # Linux/macOS 启用 SSH sudo systemctl enable ssh && sudo systemctl start ssh # Windows:启用 OpenSSH 服务器(设置 → 应用 → 可选功能) ``` 2. **容器内安装 SSH 客户端** ```dockerfile # Dockerfile 示例 FROM alpine RUN apk add --no-cache openssh-client CMD ["sh"] ``` 3. **从容器执行宿主机命令** ```bash ssh -o StrictHostKeyChecking=no \ -i /path/to/ssh_key \ # 挂载的 SSH 密钥 user@host.docker.internal \ # 宿主机 DNS "宿主机命令" # 例如 "ls /" ``` #### 运行示例: ```bash docker run -it --rm \ -v ~/.ssh/id_rsa:/root/.ssh/id_rsa \ # 挂载 SSH 私钥 my-ssh-image \ ssh user@host.docker.internal "date && whoami" ``` --- ### ⚙ 方法 2:使用 Docker Socket(高风险) > ⚠️ 警告:此方法会授予容器完全控制宿主机的权限,仅适用于开发环境 ```bash docker run -it --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ # 挂载 Docker Socket docker:cli \ sh -c "docker run --rm -v /:/host alpine chroot /host sh -c '宿主机命令'" ``` #### 示例(获取宿主机文件): ```bash docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker:cli \ docker run --rm -v /:/host alpine cat /host/etc/hosts ``` --- ### 📂 方法 3:文件共享 + 脚本执行 1. **宿主机创建脚本** (`/host_scripts/run.sh`): ```bash #!/bin/sh echo "执行来自容器的命令: $@" $@ # 实际执行传入的命令 ``` 2. **运行容器挂载脚本目录**: ```bash docker run -it --rm \ -v /path/to/host_scripts:/scripts \ # 挂载脚本目录 alpine \ sh -c "chmod +x /scripts/run.sh && /scripts/run.sh 'ls /'" ``` --- ### 🔍 关键注意事项 1. **网络限制**: - `host.docker.internal` 不支持 ICMP(无法 ping) - 访问宿主机服务需开放对应端口(如 SSH 默认 22) 2. **安全建议**: - 优先使用 SSH 密钥认证(禁用密码登录) - 限制挂载 `docker.sock` 的场景 - 容器内使用非 root 用户执行命令 3. **平台差异**: - **macOS/Windows**:`host.docker.internal` 指向宿主机 - **Linux**:需要 Docker Engine v20.10+ 支持[^2] > 💡 提示:通过 `docker context create --docker "host=ssh://user@host"` 可建立远程管理上下文[^3]。 --- ### ❓相关问题 1. 如何在 Docker 容器中安全地管理 SSH 密钥? 2. 使用 `docker.sock` 挂载时有哪些安全风险?如何规避? 3. 如何配置 Docker Desktop 的网络规则以允许自定义端口访问宿主机? 4. 在 Windows 宿主机上如何通过 PowerShell 实现 Docker 容器内命令执行? [^1]: Docker 官方文档:Networking features in Docker Desktop [^2]: Docker Engine v20.10 Release Notes [^3]: Docker Context 管理指南
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值