通过 Ubuntu 堡垒到私有子网中的 EC2 实例的 SSH 隧道

Posted

技术标签:

【中文标题】通过 Ubuntu 堡垒到私有子网中的 EC2 实例的 SSH 隧道【英文标题】:SSH Tunnel through Ubuntu bastion to EC2 instance in private subnet 【发布时间】:2019-09-10 03:08:30 【问题描述】:

根据此 AWS 文档:Scenario 2: VPC with Public and Private Subnets (NAT) 我有自己的 VPC,有两个子网:私有和公共。在公共子网中,我部署了一个分配有 EIP 的 Ubuntu 16.04 实例。它还有下一个安全组入站规则:

Type   Protocol Port Range Source            Description
SSH    TCP      22         xx.xx.xx.xx/32    Home IP

并相应地出站:

Type   Protocol Port Range Source            Description
SSH    TCP      22         sg-xxprivatexx    Security group ID for instance in private subnet

看起来不错,我可以在我家的外部 ssh 它。没问题。

在私有子网中,我部署了另一台带有下一个安全组(入站规则)的 Ubuntu 16.04 机器:

Type   Protocol Port Range Source            Description
HTTP   TCP      80         sg-xxpublicxxx    Security Group ID for bastion instance in public subnet
SSH    TCP      22         sg-xxpublicxxx    -

并且没有出站规则(实际上它打开了 80、443 个出站端口,但我猜它不是一个有趣的部分)。而且我仍然可以使用堡垒中的ssh 访问此虚拟机。

现在我只想做一件简单的事情——运行 ssh 端口转发,这样我就可以在我的家用 PC 浏览器上运行 localhost:8080 并查看我在我的私有实例上发布的网页。如果我从here 和here(以及here)正确理解它,我必须运行类似:

 ssh -N -v -L 8080:10.0.1.112:80 ubuntu@3.121.46.99

我猜这基本上意味着:只需将来自 IP 10.0.1.112:80 的私有子网实例的流量通过我的堡垒 VM 转发到我的 localhost:8080,用户名 ubuntu 托管在 EIP 3.121.46.99 上。

调试以行结束:

debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: RSA SHA256:ZyVHgnF8z5vE5gfNr1S2JDfjhdydZVTNevPRgJZ+sRA /home/matterai/.ssh/key.pem
debug1: Authentications that can continue: publickey
debug1: Trying private key: /home/matterai/.ssh/id_rsa
debug1: Trying private key: /home/matterai/.ssh/id_dsa
debug1: Trying private key: /home/matterai/.ssh/id_ecdsa
debug1: Trying private key: /home/matterai/.ssh/id_ed25519
debug1: No more authentication methods to try.
matterai@3.121.46.99: Permission denied (publickey).

我玩了几天,但我仍然无法理解我做错了什么。太奇怪了:我可以ssh -A(允许转发)到我的堡垒,我可以ssh 从堡垒到我的私人实例。但是我无法建立SSH隧道来查看我的网页(将来它将是mongodb)而不会出错。需要一些建议或指出正确的方向,拜托!谢谢。

UPD#1

那好吧。如果我使用本地机器和堡垒进行手动转发,我会得到预期的结果。基本上这意味着在堡垒上运行这个命令:

ubuntu@bastion: ssh -v -N -L 5000:localhost:8000 ubuntu@10.0.1.68

之后在本地/家庭机器上运行命令:

matterai@homepc: ssh -v -N -L 5000:localhost:5000 ubuntu@3.121.46.99

当我在本地机器上向localhost:5000 发出请求时,我可以看到结果页面。如果可以将这两个命令结合起来,我可以吗? (剧透:是的,有可能:看答案!)

【问题讨论】:

用户现在还应该考虑通过 EC2 Instance Connect 进行 SSH,这消除了对堡垒主机和开放端口的需要,使用 IAM 进行身份验证,并审核所有访问权限。 @jarmod 绝对同意您的观点,但对于尚未配置 EC2 Instance Connect 或具有类似网络设置但不在 AWS 中的人来说,它仍然很有用。 【参考方案1】:

好的,这很容易。希望我的回答对大家有所帮助。

    您需要使用ssh -J 选项通过堡垒虚拟机进行连接:
 -J [user@]host[:port]
         Connect to the target host by first making a ssh connection to
         the jump host and then establishing a TCP forwarding to the ulti‐
         mate destination from there.  Multiple jump hops may be specified
         separated by comma characters.  This is a shortcut to specify a
         ProxyJump configuration directive.
    然后您需要使用ssh -L 将流量从应用(或数据库)启动的目标虚拟机端口(@98​​7654324@)转发到您的本地主机端口(@98​​7654325@):
 -L [bind_address:]port:host:hostport
 -L [bind_address:]port:remote_socket
 -L local_socket:host:hostport
 -L local_socket:remote_socket
         Specifies that connections to the given TCP port or Unix socket
         on the local (client) host are to be forwarded to the given host
         and port, or Unix socket, on the remote side.  This works by
         allocating a socket to listen to either a TCP port on the local
         side, optionally bound to the specified bind_address, or to a
         Unix socket.  Whenever a connection is made to the local port or
         socket, the connection is forwarded over the secure channel, and
         a connection is made to either host port hostport, or the Unix
         socket remote_socket, from the remote machine.

        Port forwardings can also be specified in the configuration file.
         Only the superuser can forward privileged ports.  IPv6 addresses
         can be specified by enclosing the address in square brackets.

        By default, the local port is bound in accordance with the
         GatewayPorts setting.  However, an explicit bind_address may be
         used to bind the connection to a specific address.  The
         bind_address of “localhost” indicates that the listening port be
         bound for local use only, while an empty address or ‘*’ indicates
         that the port should be available from all interfaces.
    完整的 ssh 命令如下所示:
matterai@homepc: ssh -v -N -A -J ubuntu@3.121.46.99 -L 5001:localhost:8000 ubuntu@10.0.1.112

UPD:你也可以稍微简化你的命令。在~/.ssh/config 中,您可以添加您的跳转主机(堡垒)和您的最终目标虚拟机 IP:

Host bastion
        HostName 3.121.46.99
        User ubuntu
        Port 22
        IdentityFile ~/.ssh/secret.pem
        ForwardAgent yes

Host server
        HostName 10.0.1.112
        User ubuntu
        Port 22
        IdentityFile ~/.ssh/secret.pem
        ProxyJump bastion

现在,你可以运行命令了:

ssh -v -N -A -J bastion -L 80:localhost:8000 server

看起来好多了。您也可以使用 ssh server 简单地通过 ssh 连接。

【讨论】:

这绝对帮了我:D 刚刚也成功了,非常感谢;)【参考方案2】:

您的配置似乎正确,但错误是找不到用于连接的私钥。

要测试端口转发,首先使用登录公共实例的ssh 命令。

然后,获取确切的命令,然后简单地添加:-L 8080:10.0.1.112:80

如果它适用于“普通”ssh,那么它也适用于端口转发。

顺便说一下,一般来说,您永远不需要修改安全组的出站规则。默认设置允许所有出站流量。这“信任”实例上运行的应用程序,并允许它们向外与任何地方通信。您只需要在希望强制执行高安全性环境的情况下限制此类规则。

【讨论】:

好的,我可以连接,但是连接超时。顺便说一句,在我的私人实例上,我已经开始 python3 -m http.server 它在 0.0.0.0 上提供 http 服务。 SSH 日志:debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0 debug1: Connection to port 8080 forwarding to 10.0.1.112 port 80 requested. debug1: channel 2: new [direct-tcpip] channel 2: open failed: connect failed: Connection timed out debug1: channel 2: free: direct-tcpip: listening port 8080 for 10.0.1.112 port 80, connect from 127.0.0.1 port 53910 to 127.0.0.1 port 8080, nchannels 3

以上是关于通过 Ubuntu 堡垒到私有子网中的 EC2 实例的 SSH 隧道的主要内容,如果未能解决你的问题,请参考以下文章

AWS 如何从私有子网中的 EC2 实例打开网站

如何从ec2实例ssh到另一个ec2实例而不将公钥存储在其中一个实例中?

ec2 作为堡垒主机及其性能

使用knife ec2插件在VPC私有子网中创建VM

如何在带有 Terraform 的 AWS VPC 中的两个子网之间进行路由?

AWS VPC - 通过堡垒主机访问在私有子网中运行的 webapp