You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac环境下无法通过Bastion主机连接EC2实例求助

无法通过Bastion主机连接目标EC2实例问题排查

错误信息

尝试SSH连接时出现如下报错:

channel 0: open failed: connect failed: Connection timed out
stdio forwarding failed
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

Terraform配置(main.tf)

# Configure the AWS provider
provider "aws" {
  region     = "us-west-2"  # Replace with your desired AWS region
  access_key = ""
  secret_key = ""
}

# Create a VPC
resource "aws_vpc" "my_vpc" {
  cidr_block = "10.0.0.0/16"
}

# Create a public subnet for the bastion host
resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.1.0/24"  # Update with your desired CIDR block
  availability_zone = "us-west-2a"   # Update with your desired availability zone
}

# Create a security group for the bastion host
resource "aws_security_group" "bastion_security_group" {
  name        = "bastion-security-group"
  description = "Allow SSH access to bastion host"
  vpc_id      = aws_vpc.my_vpc.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # Update with your desired source IP range
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    self        = true  # Allow SSH access from within the same security group
  }
}

# Create a security group for the porse instance
resource "aws_security_group" "my_security_group" {
  name        = "my-security-group"
  description = "Allow inbound and outbound traffic"
  vpc_id      = aws_vpc.my_vpc.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # Update with your desired source IP range
  }

  ingress {
    from_port       = 22
    to_port         = 22
    protocol        = "tcp"
    security_groups = [aws_security_group.bastion_security_group.id]  # Allow SSH access from bastion_security_group
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    self        = true  # Allow SSH access from within the same security group
  }

  egress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # Update with the desired destination IP range or remove the cidr_blocks to allow all outbound traffic
  }
}

# Create the bastion host instance
resource "aws_instance" "bastion_host" {
  ami                          = "ami-03f65b8614a860c29"  # Replace with the ID of your desired AMI
  instance_type                = "t2.micro"               # Update with your desired instance type
  key_name                     = "bastion_key_pair"       # Replace with your bastion host key pair name
  vpc_security_group_ids       = [aws_security_group.bastion_security_group.id]
  subnet_id                    = aws_subnet.public_subnet.id
  associate_public_ip_address  = true  # Assign a public IP to the bastion host

  # Additional configuration for the bastion host
  # ...
}

# Create an EC2 instance for the porse microservice
resource "aws_instance" "porse_instance" {
  count                  = var.stop_instance ? 0 : 1
  ami                    = "ami-03f65b8614a860c29"  # Replace with the ID of your desired AMI
  instance_type          = "t2.micro"
  key_name               = "bastion_key_pair"  # Replace with your key pair name
  vpc_security_group_ids = [aws_security_group.my_security_group.id]
  subnet_id              = aws_subnet.public_subnet.id

  # You may need to add additional configuration options based on your specific requirements
}

# Create a private subnet
resource "aws_subnet" "my_subnet" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.0.0/24"  # Update with your desired CIDR block for the private subnet
  availability_zone = "us-west-2a"   # Update with your desired availability zone
}

# Create an internet gateway
resource "aws_internet_gateway" "my_internet_gateway" {
  vpc_id = aws_vpc.my_vpc.id
}

# Create a route table
resource "aws_route_table" "public_subnet_route" {
  vpc_id = aws_vpc.my_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.my_internet_gateway.id
  }
}

# Associate the route table with the subnet
resource "aws_route_table_association" "public_subnet_association" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_subnet_route.id
}

# Declare variables
variable "stop_instance" {
  description = "Flag to stop or start the EC2 instance"
  type        = bool
  default     = false
}

已尝试的排查步骤

  • 确认EC2实例的安全组允许来自Bastion主机安全组的SSH(22端口)流量
  • 检查子网关联的网络ACL,确保允许两台实例间的SSH流量
  • 确认两台实例均处于运行状态且位于同一子网,但两台实例间Ping不通

问题分析与修复方案

核心问题

  1. 目标实例安全组出站规则过度限制:my_security_group仅允许TCP 22端口出站,导致实例无法发起ICMP(ping)、DNS解析等必要网络操作,直接影响连通性和SSH会话建立。
  2. 缺少ICMP流量授权:两台实例的安全组均未配置允许ICMP规则,导致ping测试失败。
  3. 安全组规则冗余且存在安全风险:目标实例安全组中开放了0.0.0.0/0的SSH访问,违背Bastion架构的安全原则。

修复步骤

1. 修正目标实例安全组配置

更新my_security_group,移除冗余规则,开放必要的入站/出站流量:

resource "aws_security_group" "my_security_group" {
  name        = "my-security-group"
  description = "Allow inbound traffic from bastion and all outbound traffic"
  vpc_id      = aws_vpc.my_vpc.id

  # 仅允许来自Bastion安全组的SSH访问
  ingress {
    from_port       = 22
    to_port         = 22
    protocol        = "tcp"
    security_groups = [aws_security_group.bastion_security_group.id]
  }

  # 允许来自Bastion的ICMP ping请求
  ingress {
    from_port       = -1
    to_port         = -1
    protocol        = "icmp"
    security_groups = [aws_security_group.bastion_security_group.id]
  }

  # 允许所有出站流量(生产环境可按需细化规则)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

2. 优化Bastion安全组配置

移除冗余的self=true规则,补充完整的出站规则:

resource "aws_security_group" "bastion_security_group" {
  name        = "bastion-security-group"
  description = "Allow SSH access from trusted IPs and all outbound traffic"
  vpc_id      = aws_vpc.my_vpc.id

  # 建议替换为你的公网IP段,缩小访问范围
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # 允许所有出站流量(包括SSH到目标实例、ICMP ping等)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

3. 将目标实例迁移到私有子网(最佳实践)

将业务实例部署到私有子网my_subnet,避免直接暴露在公网:

resource "aws_instance" "porse_instance" {
  count                  = var.stop_instance ? 0 : 1
  ami                    = "ami-03f65b8614a860c29"
  instance_type          = "t2.micro"
  key_name               = "bastion_key_pair"
  vpc_security_group_ids = [aws_security_group.my_security_group.id]
  subnet_id              = aws_subnet.my_subnet.id  # 改为私有子网
}

4. 验证SSH配置

确保本地~/.ssh/config配置正确,示例如下:

Host bastion
  HostName <bastion-public-ip>
  User ec2-user
  IdentityFile ~/.ssh/bastion_key_pair.pem

Host target
  HostName <target-private-ip>
  User ec2-user
  IdentityFile ~/.ssh/bastion_key_pair.pem
  ProxyJump bastion

验证流程

  1. 应用Terraform配置:terraform apply
  2. 登录Bastion主机:ssh bastion
  3. 在Bastion内ping目标实例私有IP,确认连通性
  4. 尝试从Bastion SSH到目标实例:ssh <target-private-ip>

内容的提问来源于stack exchange,提问作者user2615724

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:37:04