基于 Amazon EC2 和 Amazon Systems Manager Session Manager 的堡垒机的设计和自动化实现
文章目录
- 1. 背景
- 2. 云上堡垒机设计
- 2.1 安全设计
- 2.2 高可用和弹性设计
- 2.3 监控告警设计
- 2.4 自动化部署设计
- 2.4.1 堡垒机代码设计
- 2.4.2 Session Manager 配置设计
- 2.4.3 堡垒机 IAM 角色设计
- 3. 部署堡垒机
- 3.1 堡垒机部署架构图
- 3.2 堡垒机自动化部署
- 4. 堡垒机使用场景
- 4.1 堡垒机使用前置条件
- 4.2 堡垒机使用场景实操
- 4.2.1 场景一:通过亚马逊云科技管理控制台/命令行登录堡垒机
- 4.2.2 场景二:通过堡垒机实现远程主机端口转发
- 4.2.3 场景三:通过本地 SSH 连接到堡垒机
- 5. 未来架构演进
- 6. 总结
- 7. 参考文档
1. 背景
在很多企业的实际应用场景中,特别是金融类的客户,大部分的应用都是部署在私有子网中,如何能够让客户的开发人员和运维人员从本地的数据中心中安全的访问云上资源,堡垒机是一个很好的选择。
传统堡垒机的核心实现原理是基于 SSH 协议的安全连接,通常运用 SSH(Secure Shell)协议实现数据的加密通信。SSH 为安全身份验证和数据加密提供了可靠保障,从而确保了连接的安全性。然而,传统的自建堡垒机在其管理和运维方面面临着多种挑战:
- 部署与维护复杂性:自建堡垒机的部署和配置往往涉及多个复杂步骤和组件,导致管理和维护的工作量显著增加。
- 安全性风险:自行管理多个密钥和凭证可能会增加安全漏洞的风险。若密钥管理不当,可能导致未经授权的访问。
- 可用性问题:自建堡垒机常常无法实现高可用性和弹性,多用户同时访问时可能出现性能问题,影响用户体验。
- 扩展困难:随着用户数量和需求的增加,自建堡垒机可能难以灵活扩展,导致资源分配不均。
- 更新和升级:自建堡垒机需要定期进行更新和升级,以保持安全性和性能,然而这可能会导致业务中断或不稳定情况。
- 外网暴露:传统堡垒机需要在云上环境中部署一个有外网访问的权限的机器,增加了被攻击的风险。
与传统方式不同,基于 Amazon Systems Manager Session Manager 的堡垒机通过建立双向加密通道,连接客户端和远程节点,并采用 TLS 1.2 进行流量加密和 Sigv4 签名请求。这一方式具备显著优势:
- 一键式部署: 该方案极大简化了堡垒机部署流程,从而减少了部署难度和运维成本。
- 卓越安全性: Session Manager 提供了加密和身份验证功能,保障连接的安全性。
a. 基于 Amazon Identity and Access Management (IAM) 角色的最小权限原则,管理员能够通过集中的IAM 策略管理堡垒机的访问授权。 b. 无需管理堡垒机密钥。 c. 支持云上私有子网部署,无需部署在公有子网中,且无需打开入站端口。
- 高可用性: 通过弹性伸缩功能实现了堡垒机的跨可用区高可用性。
- 可扩展性: 基于 CPU 利用率的弹性伸缩策略能够自动调整容量,以适应不同流量访问的需求。
- 简化管理: Systems Manager Session Manager 是一项无需用户自行管理实例的托管服务。无需预先启动实例,也无需将实例直接暴露在公网上,从而降低了管理复杂性。
- 端口转发与跨平台支持:通过 Session Manager,可在本地客户端进行远程节点端口转发,并实现连接。同时,它对 Linux、Windows、Mac 等多种操作系统平台提供了跨平台访问支持。
- 全面的日志记录与审计:Session Manager 支持多种方式进行日志记录,涵盖登录时间、命令执行等内容,以确保会话连接活动得到完整记录。这些记录可用于审计和故障排除。
- 提供监控告警功能:针对堡垒机的性能指标进行监控告警,以便在性能异常时及时收到通知。
基于 Session Manager 的堡垒机为访问管理提供了高效、安全、高可用的解决方案,成为提升操作效率和保障安全性的理想选择。堡垒机作为一种安全措施,允许用户通过中间主机来访问位于私有子网中的实例或资源。它作为一座桥梁,帮助用户在安全的环境下连接到内部资源,同时减少对直接连接的需求,从而降低被攻击的风险。
对于企业的安全管理员来说,堡垒机可以增强安全性、简化网络配置、降低网络资源暴露风险、提供审计跟踪,对于开发运维人员来说,他们可以在本地环境中使用熟悉的开发、运维工具,如数据库客户端、浏览器、RDP 等去访问云上私有资源,大大提高生产效率。
本文主要阐述的是基于 Amazon Systems Manager 的 Session Manager 特性和 Amazon EC2 堡垒机的设计和实现。主要内容包括堡垒机的架构设计、安全设计、日志监控设计、高可用弹性设计以及自动化部署设计等,同时针对堡垒机在不同场景中的使用方式和脚本进行举例说明。
2. 云上堡垒机设计
2.1 安全设计
在进行云上堡垒机设计时,安全是第一个需要考虑的要求。Session Manager 是一种无需通过公网 IP 或 SSH 密钥来连接到 EC2 实例的服务,它通过 Systems Manager 的控制台或 CLI 来创建和管理安全的交互式会话。其安全设计主要考虑以下四点:
- IAM 权限和访问控制:
Session Manager 权限: 确保只有授权的用户或角色拥有使用 Session Manager 的权限。为用户或角色分配适当的 IAM 策略,限制其对 Session Manager 的访问,一般情况下,通过与客户已有的 AD 进行集成,通过分组来控制启动 Session Manager 的权限。
多因素认证(MFA): 强制启用多因素认证,增加用户身份验证的安全性。
- VPC 和子网安全性:
控制对 Session Manager 的网络访问:设置 VPC Endpoints 的安全组仅允许来自堡垒机及私有子网中主机的访问,并且设置 VPC Endpoints 的策略,以限制特定受信任实体才能访问。
- 日志和审计:
监控 Session Manager 会话:启用 CloudTrail 以记录 Session Manager 的 API 调用活动,以便审计和监控用户对会话的操作;配置 Session Manager 参数,发送会话日志到 Amazon CloudWatch 日志组和 S3 存储桶,确保用户在会话中的所有操作均被记录,CloudWatch 日志组中的数据将保存 3 个月,S3 桶中的会话日志将持久存储以满足安全监管和审计需求。同时,通过脚本来实现对本地 Session Manager 插件 SSH 登录上的操作进行详细记录,并存储在指定的存储桶中。
- 安全加密:
加密各类堡垒机相关资源:使用 Amazon Key Management Service(KMS)对 Session Manager 的会话进行加密,加密 Amazon CloudWatch 日志组及 S3 存储桶,以确保会话和日志的安全性。
2.2 高可用和弹性设计
堡垒机的高可用设计可以确保在发生故障或负载增加时,堡垒机仍然能够保持可用,并继续提供安全的访问控制。
- 堡垒机的高可用性
使用 Auto Scaling Group(ASG): 配置堡垒机所在的 EC2 实例为一个 Auto Scaling Group。当堡垒机实例的负载增加时,ASG 会根据设置的扩展规则自动增加实例数量,保持高可用性。
设置负载均衡: 当多个堡垒机实例同时运行时,可以使用负载均衡器来分发流量,确保各个实例的负载均衡。负载均衡器还可以在某些实例出现故障时自动将流量路由到其他健康的实例,提高了整体的可用性。
- 定时扩展和缩减
通过 Auto Scaling Group 的定时规则,控制堡垒机的启动和关机时间,从而来节约堡垒机的费用。
2.3 监控告警设计
Amazon CloudWatch 指标监控: CloudWatch 可以监控 EC2 实例和其他亚马逊云资源的性能指标。可监控实例的 CPU 使用率、内存利用率、磁盘等关键指标。并通过 Amazon SNS 服务设置报警,以便在性能异常时及时收到通知。
2.4 自动化部署设计
2.4.1 堡垒机代码设计
考虑到堡垒机的高可用设计,在其中一台机器宕机的情况下,可以自动、快速的拉起一台新的堡垒机以供使用,我们采取 EC2 launch template 的方式进行堡垒机的构建,以下是 IaC 样例代码:
通过弹性伸缩启动模版创建堡垒机的 IaC 代码样例,包含启动模版、弹性伸缩组、弹性规则等。
## 创建Bastion的launch template
resource "aws_launch_template" "bastion_template" {name = "bastion_template"block_device_mappings {device_name = "/dev/xvda"ebs {volume_size = 8encrypted = true}}iam_instance_profile {name = aws_iam_instance_profile.bastion_ec2_profile.id}image_id = data.aws_ami.linux_2023_image.idinstance_initiated_shutdown_behavior = "terminate"instance_type = var.bastion_instance_typemonitoring {enabled = true}network_interfaces {associate_public_ip_address = falsedevice_index = 0security_groups = [aws_security_group.bastion.id]subnet_id = element(module.vpc.private_subnets, 0)delete_on_termination = true}user_data = base64encode(templatefile("${path.module}/templates/user_data.sh.tftpl",{##传入值到user data中所需要的变量中}))
}## 创建Bastion的弹性伸缩组
resource "aws_autoscaling_group" "bastion_asg" {launch_template {id = aws_launch_template.bastion_template.idversion = "$Latest"}availability_zones = ["${var.region}a","${var.region}b"]name = "bastion_daily"max_size = 1min_size = 1health_check_grace_period = 300health_check_type = "EC2"force_delete = truetermination_policies = ["OldestInstance"]tag {key = "Name"value = "bastion"propagate_at_launch = true}
}## 创建Bastion的弹性伸缩规则-样例中使用定时规则
resource "aws_autoscaling_schedule" "bastion_scale_down" {scheduled_action_name = "bastion_scale_down"min_size = 0max_size = 0desired_capacity = 0recurrence = "0 20 * * *" # 20:00 UTC +8 时间time_zone = "Asia/Chongqing"autoscaling_group_name = aws_autoscaling_group.bastion_asg.name
}resource "aws_autoscaling_schedule" "bastion_scale_up" {scheduled_action_name = "bastion_scale_up"min_size = 1max_size = 1desired_capacity = 1recurrence = "0 8 * * *" # 8:00 UTC +8 时间time_zone = "Asia/Chongqing"autoscaling_group_name = aws_autoscaling_group.bastion_asg.name
}## 或者基于CPU利用率的弹性伸缩规则(样例)
resource "aws_autoscaling_group" "bation_cpu" {name = "bastion-cpu-asg"launch_configuration = aws_launch_configuration.bastion_template.namemin_size = 2max_size = 4desired_capacity = 2metric_trigger {metric_name = "CPUUtilization"namespace = "AWS/EC2"statistic = "Average"unit = "Percent"threshold = 70 # CPU利用率超过70%时扩容comparison_operator = "GreaterThanOrEqualToThreshold"dimensions = {AutoScalingGroupName = aws_autoscaling_group.bastion_cpu.name}}scaling_policy {name = "scale-up-policy"adjustment_type = "ChangeInCapacity"scaling_adjustment = 1cooldown = 300 # 冷却时间300s}
定义堡垒机的 EC2 用户数据代码样例
在创建堡垒机时,不仅仅是单独的创建一台 EC2 的实例,还需要针对用于该 EC2 的实例进行安全加固、安装相应的工具、设置对于堡垒机的监控等功能,以下是 IaC 代码中,用于 EC2 实例初始化的用户数据(User Data)样例。
## 安全加固
yum -y update --security## 仅允许ec2-user访问该目录
mkdir /var/log/bastion
chown ec2-user:ec2-user /var/log/bastion
chmod -R 770 /var/log/bastion
setfacl -Rdm other:0 /var/log/bastion## Make OpenSSH execute a custom script on logins
echo -e "\\nForceCommand /usr/bin/bastion/shell" >> /etc/ssh/sshd_config
echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config
awk '!/X11Forwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config
echo "X11Forwarding no" >> /etc/ssh/sshd_configsed -i "s/002/022/g" /etc/profile
umask 022## SSH命令记录脚本
mkdir /usr/bin/bastion
cat > /usr/bin/bastion/shell << 'EOF'# The format of log files is /var/log/bastion/YYYY-MM-DD_HH-MM-SS_userLOG_FILE="`date --date="today" "+%Y-%m-%d_%H-%M-%S"`_`whoami`"LOG_DIR="/var/log/bastion/"echo ""echo "NOTE: This SSH session will be recorded"echo "AUDIT KEY: $LOG_FILE"echo ""SUFFIX=`mktemp -u _XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`script -qf --timing=$LOG_DIR$LOG_FILE$SUFFIX.time $LOG_DIR$LOG_FILE$SUFFIX.data --command=/bin/bash
EOFchmod a+x /usr/bin/bastion/shell
chown root:ec2-user /usr/bin/script
chmod g+s /usr/bin/script##关闭根用户登录
systemctl stop sshd
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PermitEmptyPasswords no" >> /etc/ssh/sshd_config
systemctl start sshd## 安装CloudWatch Agent,进行系统日志收集及性能指标收集
sudo yum -y install amazon-cloudwatch-agent
sudo yum install -y collectd
cat > /opt/aws/amazon-cloudwatch-agent/etc/config.json << _EOF_
{"agent": {"metrics_collection_interval": 60,"run_as_user": "root"},"logs": {"logs_collected": {"files": {"collect_list": [{"file_path": "/var/log/messages","log_group_name": "/aws/ec2/bastion/messages","log_stream_name": "{instance_id}","retention_in_days": 30},{"file_path": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log","log_group_name": "/aws/ec2/bastion/amazon-cloudwatch-agent","log_stream_name": "{instance_id}","retention_in_days": 30}]}}},"metrics": {"aggregation_dimensions": [["InstanceId"]],"append_dimensions": {"AutoScalingGroupName": "$${aws:AutoScalingGroupName}","InstanceId": "$${aws:InstanceId}"},"metrics_collected": {"collectd": {"metrics_aggregation_interval": 60},"disk": {"measurement": [{"name":"used_percent","rename":"disk_used_percent"}],"metrics_collection_interval": 60,"resources": ["*"]},"mem": {"measurement": [{"name":"used_percent","rename":"mem_used_percent"} ],"metrics_collection_interval": 60},"statsd": {"metrics_aggregation_interval": 60,"metrics_collection_interval": 10,"service_address": ":8125"}}}
}
_EOF_sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/config.json -s
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a start
设计和创建堡垒机安全组
根据 Session Manager 安全组的最佳实践,本方案中堡垒机的安全组设计如下:
入站规则:
| 源 | 协议 | 端口 | 备注 |
|---|---|---|---|
| NA | NA | NA | 无入站规则 |
出站规则:
| 目标 | 协议 | 端口 | 备注 |
|---|---|---|---|
| VPC CIDR | TCP | 0-65535 | 允许访问 VPC 内部资源 |
| VPC endpoints Security group ID | HTTPS | 443 | 允许访问 VPC Interface endpoints |
| VPC endpoints S3 prefix list | HTTPS | 443 | 允许访问 S3 Gateway endpoint |
IaC 代码设计样例如下:
# 创建堡垒机安全组并配置规则
resource "aws_security_group" "bastion" {description = "Ingress should be only from Systems Session Manager"name = "bastion-sg"vpc_id = module.vpc.vpc_idtags = merge({Name = "bastion-sg"})
}resource "aws_security_group_rule" "basion_egress_1" {security_group_id = aws_security_group.bastion.iddescription = "bastion_to_local_VPC_CIDRs"type = "egress"from_port = "0"to_port = "65535"protocol = "TCP"cidr_blocks = [local.vpc_cidr]
}resource "aws_security_group_rule" "basion_egress_2" {security_group_id = aws_security_group.bastion.iddescription = "bastion_egress_to_inteface_endpoints"type = "egress"from_port = "443"to_port = "443"protocol = "TCP"source_security_group_id = aws_security_group.vpc_endpoints.id
}resource "aws_security_group_rule" "bastion_linux_3" {security_group_id = aws_security_group.bastion.iddescription = "bastion_linux_egress_to_s3_endpoint"type = "egress"from_port = "443"to_port = "443"protocol = "TCP"prefix_list_ids = [data.aws_vpc_endpoint.s3.prefix_list_id]
}
2.4.2 Session Manager 配置设计
在启用 Session Manager 时,需要对 Session Manager 进行相关的配置,如是否开启 Session 加密,是否将日志存储到 CloudWatch Logs 或者 S3 上,是否对日志进行加密,最大的 Session 时长等。我们通过创建 SSM Documents 的方式来进行配置,如以下 IaC 样例代码所示:
## ssm run shell json
{"schemaVersion": "1.0","description" : "Document for SSM log configuration","sessionType" : "Standard_Stream","inputs": {"s3BucketName" : "${bucket_name}","s3KeyPrefix" : "ssm","s3EncryptionEnabled" : true,"cloudWatchLogGroupName" : "${log_group_name}","cloudWatchEncryptionEnabled" : true,"cloudWatchStreamingEnabled": true,"kmsKeyId" : "${kms_id}","runAsEnabled": true,"idleSessionTimeout": "20","maxSessionDuration":"60",}
}## IaC code 创建SessionManagerRunShell documents
resource "aws_ssm_document" "ssm_shell" {name = "SSM-SessionManagerRunShell"document_format = "JSON"document_type = "Session"content = templatefile("${path.module}/templates/ssm_runshell.json", {bucket_name = join("-", [local.bucket_name, data.aws_caller_identity.current.account_id])log_group_name = "/aws/sessionmanager"kms_id = aws_kms_key.this.arn})
}
2.4.3 堡垒机 IAM 角色设计
在本设计中,堡垒机的 IAM 角色主要包含以下权限:
- AmazonSSMManagedInstanceCore
- CloudWatchAgentServerPolicy
- Logs 部分权限
- SSM Messages 部分权限
- S3 部分权限
- KMS 部分权限
如需自定义更多 Session Manager IAM 角色的详细可访问:自定义 Session Manager IAM 角色
以下是 IaC 代码样例:
## 关联托管的IAM Policy
resource "aws_iam_role_policy_attachment" "bastion_managed" {policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"role = aws_iam_role.bastion_role.name
}resource "aws_iam_role_policy_attachment" "bastion_managed_cloudwatch" {policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"role = aws_iam_role.bastion_role.name
}## 创建IAM 角色及关联的Policy Documents
data "aws_iam_policy_document" "bastion_assume_policy_document" {statement {actions = ["sts:AssumeRole"]principals {type = "Service"identifiers = ["ec2.amazonaws.com"]}}
}resource "aws_iam_role" "bastion_role" {name = "bastion_ec2_role"path = "/"assume_role_policy = data.aws_iam_policy_document.bastion_assume_policy_document.jsontags = merge({Name = "bastion_linux_ec2_role"},)
}
3. 部署堡垒机
本章将介绍如何通过基础设施即代码(Infrastructure as code)的方式一键式构建云上堡垒机,通过 Terraform 进行相应的 IaC 代码开发。
3.1 堡垒机部署架构图
根据云上堡垒机的设计,我们在堡垒机的部署中,将使用到亚马逊云上的多种服务:如Amazon CloudWatch、Key Management Service(KMS) 、 Identity and Access Management(IAM)、Systems Manager、Amazon Simply Notification Service(SNS)、Amazon Simple Storage Service(S3) 、Amazon PrivateLink、Amazon EC2 以及Amazon EC2 Auto Scaling等,以下为部署架构图:

图 3-1 堡垒机部署架构图
以下对部署中所使用到的主要亚马逊云相关服务的用途进行简单介绍:
- Amazon EC2/Amazon EC2 Auto Scaling:在 EC2 上进行堡垒机的部署,并通过 AutoScaling 确保堡垒机的高可用;
- Amazon Simple Storage Service(S3):用于存放通过 Session Manager 和 SSH 登录到堡垒机上所产生的操作日志信息;
- Amazon VPC endpoints:用于堡垒机在没有外网访问的条件下,进行安全的访问如 Amazon CloudWatch(Logs/Monitoring)、Amazon S3、Systems Manager、Amazon KMS 等服务;
- Amazon CloudWatch:用于存放通过控制台的 Session Manager 功能访问堡垒机的操作日志存储;
- Amazon KMS:用于加密堡垒机部署过程中的相关服务,如 Session 加密、CloudWatch logs 加密、S3桶加密等;
- Amazon Simply Notification Service:用于接受 Bastion Host 在 CPU/Memory/磁盘超过阈值的时候的告警信息。
需要创建的 Endpoints 列表:
| 序号 | 名称 | 类型 | 用途 |
|---|---|---|---|
| 1 | com.amazonaws..ssm | Interface | 与 Session Manager 进行安全交互 |
| 2 | com.amazonaws..ssmmessages | Interface | 用于 SSM Agent 到 Session Manager 的 API 操作 |
| 3 | com.amazonaws..ec2messages | Interface | 用于 SSM Agent 到 Session Manager 的 API 操作 |
| 4 | com.amazonaws..logs | Interface | 与 CloudWatch 服务进行安全交互 |
| 5 | com.amazonaws..monitoring | Interface | 与监控告警服务进行安全交互 |
| 6 | com.amazonaws..kms | Interface | 与 KSM 服务进行安全交互 |
| 7 | com.amazonaws..s3 | Gateway | 与 S3 服务进行安全交互 |
| 8 | eice-*.ec2-instance-connect-endpoint..amazonaws.com | EC2 Instance Connect Endpoint | 发送 Public Key 到远端 EC2(中国区不支持该功能) |
3.2 堡垒机自动化部署
当 IaC 代码开发完成后,可以将该代码集成在其他资源的 CICD pipeline 中,也可以通过 Terraform 命令,直接进行部署。
# Terraform plan 检查要部署的Bastion资源
$ terraform plan -var-file=common.tfvars ## common.tfvars包含堡垒机所需的相关参数# Terraform apply 执行部署
$ terraform apply -var-file=common.tfvars
等到命令执行完成后,登录到亚马逊云科技管理控制台检查相应资源是否按照预期部署完成。
4. 堡垒机使用场景
4.1 堡垒机使用前置条件
如果要在本地机器上使用堡垒机,需要满足以下条件:
- 确保亚马逊云上堡垒机已经部署完成,并且处于 running 状态;
- 确保网络联通性,确认堡垒机能访问私网环境中的 RDS 数据库、WebServer EC2 等;
- 确保你本地使用的 IAM 角色至少具有以下权限:
ec2:DescribeInstances
ssm:StartSession
ec2-instance-connect:SendSSHPublicKey
- 确保本地环境中正确安装了亚马逊云命令行工具( CLI V2) 和 Session Manager 插件
4.2 堡垒机使用场景实操
假设客户在亚马逊云上的私有子网中,部署了一个 Web 应用,包含 Web 前端和服务后端以及 RDS 数据库(以 SQL Server 为例)。该客户对于安全性的要求非常高,云上 VPC 环境中没有 Internet 访问,也没有在本地网络与云上环境之间搭建专线直连(Direct Connect)和 VPN。
但客户的开发人员和运维人员,要求提供一个安全、高效、可靠的方式从本地的客户端、应用程序、浏览器去访问云上资源,以提高开发、运维效率。下图为堡垒机实操环境的部署示意图:

图 4-1 堡垒机实操环境部署示意图
4.2.1 场景一:通过亚马逊云科技管理控制台/命令行登录堡垒机
在这个场景中,开发人员或者运维人员通过公司 AD 集成的账号拿到了相应的角色权限,直接登录到亚马逊云的管理控制台,然后通过 Session Manager 直接连接到堡垒机上进行操作。操作步骤如下:
- 方式一: 直接进入到 EC2 控制台,选择堡垒机,然后点击“
Connect”进行连接 - 方式二:进入到
Systems Manager→ Session Manager→ Start Session,然后选择堡垒机进行连接
两种方式登录后,进入的界面如下图所示:

图 4-2 通过控制台登录堡垒机
或者在本地启动 SSM Session Manager 的插件,从本地电脑中,直接访问堡垒机:
## 通过CLI获取Bastion的Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \--filters "Name=tag:Name,Values=bastion_linux" \--query 'Reservations[0].Instances[0].InstanceId' --output text) ## 启动本地会话
$ aws ssm start-session --target $InstanceID

图 4-3 通过 CLI 从本地机器登录堡垒机
通过控制台或者本地 CLI 进入到堡垒机后,所有的操作都会被记录到 Amazon CloudWatch Log Group “/aws/sessionmanager”,日志保留时间为 3 个月,并且还会上传到 S3 桶(S3 桶名:bastion-audit-log-bucket-<AccountID>,路径为:ssm/)中做持久化存储。

图 4-4 日志组中存储的堡垒机操作审计日志

图 4-5 S3 中存储的堡垒机操作审计日志
4.2.2 场景二:通过堡垒机实现远程主机端口转发
在该场景中,开发人员或者运维人员通过公司 AD 集成的账号拿到了相应的角色权限,然后在本地启动 Session Manager 插件 来进行远程主机的端口转发,通过这种方式,开发人员或运维人员可以方便的使用本地客户端进行操作云上资源,如访问云上数据库和访问 WebServer 等。以下命令是启动如何在本地机器上实现远程主机端口转发:
## 通过CLI获取Bastion的Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \--filters "Name=tag:Name,Values=bastion_linux" \--query 'Reservations[0].Instances[0].InstanceId' --output text) ## 启动远程主机端口转发,请替换掉命令中的<>为实际的远程端口、本地端口以及远程主机IP或者DNS
$ aws ssm start-session --target $InstanceID \--document-name AWS-StartPortForwardingSessionToRemoteHost \--parameters '{"portNumber":["<Remote_Host_Port_Number>"],"localPortNumber":["<LocalPortNumber>"],"host":["<Remote_Host_DNS/IP>"]}'
(1) 远端数据库端口转发
以在本地访问云上 SQLServer 数据库为例子,端口号为 1433,本地端口号为 12345,远程主机 DNS 为:“bastion-test-db.xxxxx.<REGION>.rds.amazonaws.com”,启动后,如下图所示:

图 4-6 本地启动远程主机端口转发(DNS)
打开本地 SQLServer 客户端,输入 RDS Server 端地址和端口:“127.0.0.1,12345”,并输入登录数据库的账号和密码,如下图所示:

图 4-7 配置本地数据库客户端连接
点击“Connect”,即可访问云上 RDS 数据库并进行操作:

图 4-8 本地数据库客户端连接 RDS 成功
(2) 远端服务器端口转发
以本地通过浏览器访问 Web Server 为例,端口号为 80,本地端口号为 8080,远程主机 IP 为:“10.99.3.132”,启动后,如下图所示:

图 4-9 本地启动远程端口转发(IP 地址)
通过本地浏览器访问 127.0.0.1:8080,可看到能够成功访问到位于私有网络中的 WebServer:

图 4-10 本地浏览器成功访问 WebServer
4.2.3 场景三:通过本地 SSH 连接到堡垒机
在开发人员或者运维人员在实际工作中,偶尔会需要通过 SSH 连接到堡垒机或者远端的主机上进行调试或者运维,并上传相应的文件到堡垒机上。
一般情况下,运维人员需要拿到 EC2 的密钥并确保安全组中包含有 22 端口及客户端的 IP 地址的入站规则,然后才能连接到云上服务器上,这种情况不仅增加了密钥管理的难度,同时对于只存在私有网络中的服务器且本地数据中心和云上环境没有互联的场景是一个很大的挑战。
通过 ec2-instance-connect 服务特性并结合 Session Manager 可以方便的满足客户通过 SSH 访问云上 EC2 的情景。
## Step 1: 通过 CLI 获取 Bastion 的 Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \--filters "Name=tag:Name,Values=bastion_linux" \--query 'Reservations[0].Instances[0].InstanceId' --output text)## Step 2: 生成临时 ssh key
$ echo -ne "Generating SSH key pair................\r"
$ echo -e 'y\n' | ssh-keygen -t rsa -f temp-key -N '' > /dev/null 2>&1## Step 3: 发送生成 SSH public key 到堡垒机中,根据实际情况替换掉命令行中的变量
$ echo -ne "Pushing public key to instance.........\r"
$ aws ec2-instance-connect send-ssh-public-key --region $AWS_DEFAULT_REGION \--instance-id $instanceId --availability-zone <az> \--instance-os-user <ssm_user> \--ssh-public-key file://temp-key.pub > /dev/null 2>&1## Step 4: 修改 ~/.ssh/config 配置(仅需要一次配置)
Host test-ssh-bastionIdentityFile ~/test/temp-keyStrictHostKeyChecking noUserKnownHostsFile /dev/nullLogLevel QUIETUser ec2-userProxyCommand sh -c "aws ssm start-session --target $(aws ec2 describe-instances --no-cli-pager \--filters 'Name=tag:Name,Values=bastion_linux' \--query 'Reservations[0].Instances[0].InstanceId' --output text) \--document-name AWS-StartSSHSession --parameters 'portNumber=%p' --region us-east-1"## Step 5: 修改完成后,通过 ssh 就可以连接到堡垒机中,如下图所示
$ ssh test-ssh-bastion
将以上代码中的 Step1 到 Step3 编写成一个脚本,在每次执行 ssh 之前,先运行该脚本,确保新生成的 SSH Key 有效(通过 send-ssh-public-key 上传到 EC2 上的 Key 有效期只有 60s)。

图 4-11 启动本地 SSH 访问堡垒机
注意: 如果使用动态生成 SSH Key 的方式,需要先创建“EC2 Instance Connect Endpoint”,同时确保本地电脑上使用的 IAM 角色包含有“ec2-instance-connect:SendSSHPublicKey”的权限。另外,亚马逊云科技中国区暂时不支持该 Endpoint 类型的创建。
通过本地 Session Manager 插件 SSH 进入到堡垒机后,所有的操作都会上传到 S3 桶(S3 桶名:bastion-audit-log-bucket-<AccountID>,路径为:logs/)中做持久化存储。

图 4-12 S3 中存储的在本地通过 SSH 操作堡垒机的审计日志
除通过 SSH 登录到堡垒机外,SSM 还可以支持 SSH Socks Proxy,如下图在浏览器中设置 Proxy(以 Firefox 为例):

图 4-13 Socks Proxy 配置
使用以下代码启动 SSH Socks Proxy:
ssh -f -N -p 2200 -i temp -o "IdentitiesOnly=yes" -D 1080 ec2-user@localhost
启动后,就可以通过 Socks Proxy 访问内网的 WebServer。
5. 未来架构演进
本方案中堡垒机是根据最常用的功能,如端口转发、SSH 访问来设计的,但在一些特定的场景中,还需要设计更多复杂的堡垒机方案,如:Windows 类型的堡垒机支持、如何使用 IAM 角色对堡垒机权限进行更精细化的管理等,这些都是未来本方案演进和增强的一个方向。
目前我们方案中,创建的堡垒机类型只有一种,任何拥有启动 Session Manager 的 IAM 用户/角色都可以去访问它并进行操作,但在一些场景下,客户需要对于不同的角色使用不同的堡垒机:如角色 A 仅可以访问堡垒机 A,并通过该堡垒机上赋予的 IAM 权限进行相应的操作;角色 B 仅可以访问堡垒机 B,通过该堡垒机上赋予的 IAM 权限进行相应的操作。不同的用户角色和客户自有的 AD 域控进行集成,可以灵活的进行更精细化的权限控制。
6. 总结
本文主要介绍了基于 Amazon Systems Manager Session Manager 的堡垒机的设计和实现,并通过 IaC 自动化方式构建和部署云上堡垒机,同时基于堡垒机的使用场景进行了举例,介绍了不同场景下堡垒机的使用方法和步骤。该堡垒机方案已经集成到 Cloud Foundations 快速启动包服务中,为企业用户提供更便捷的部署方式。
7. 参考文档
- Amazon Systems Manager Session Manager 官方文档
- Amazon 官方博客:New – Port Forwarding Using AWS System Manager Session Manager
相关文章:
基于 Amazon EC2 和 Amazon Systems Manager Session Manager 的堡垒机的设计和自动化实现
文章目录 1. 背景2. 云上堡垒机设计2.1 安全设计2.2 高可用和弹性设计2.3 监控告警设计2.4 自动化部署设计2.4.1 堡垒机代码设计2.4.2 Session Manager 配置设计2.4.3 堡垒机 IAM 角色设计 3. 部署堡垒机3.1 堡垒机部署架构图3.2 堡垒机自动化部署 4. 堡垒机使用场景4.1 堡垒机…...
RFID管理方案有效提升电力物资管理效率与资产安全
在电力行业,电力资产的管理是一项重要的任务,为了实现对电力资产的精细化管理、入出库监控管理、盘点管理和巡查管理等,电力公司多采用电力资产RFID管理系统,该系统能够实时监控出入库过程,有效防止出入库错误…...
leetcode:389. 找不同
一、题目 函数原型:char findTheDifference(char * s, char * t) 二、思路 作者原先的思路是先将两个字符串从小到大排序,然后两个字符串依次比较。若出现字符串t中的元素和字符串s不相等,则说明该元素就是被添加的字母。 但是,该…...
c 函数调用过程中,调用函数的栈帧一旦被修改,被调用函数则无法正确返回。( X )
当一个函数被调用时,它的栈帧会被创建并压入调用栈中。栈帧包含了函数的局部变量、参数以及返回地址等信息。当函数执行完毕后,栈帧会被弹出,返回到调用函数的位置继续执行。 下面是一个示例代码,展示了调用函数栈帧被修改但不影…...
专为个人打造专注工作的便签APP工具推荐哪个
工作中很多人都比较懒散,工作起来动力不足,常常拖延消极怠工,等到一天结束后进行工作盘点时才发现很多项任务都没有处理完;这和日常工作不能专注于工作有很大的关系。 专注工作,在日常办公时可以选择一些好用的手机便…...
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零 文章链接:最后一块石头的重量 II 目标和 一和零 视频链接:最后一块石头的重量 II 目标和 一和零 1. LeetCode 1049. 最后一块石头的重量 II 1.1 思路…...
Windows PowerShell 和 Linux BashShell 极简对比
声明:本文不会涉及原理,详细的介绍,也不是入门文章。仅仅从使用上进行简单比较 命令 在 bash 中,一个命令是一个单独的进程;而在 PowerShell 中,命令被称为 cmdlets,他们不是独立的可执行程序&…...
校验验证码是否过期(定时刷新验证码)
需求: 我们在登录的时候会遇到通过接口请求验证码的操作,这里的验证码会有过期的时间,当我们验证码过期了,我们要进行重新刷新验证码。 我们这里根据后端返回的当前时间和过期时间判断,过期的时间超过了当前时间的时候…...
windows idea本地执行spark sql避坑
本地安装了IDEA,并配置好了相关POM,可以在本机使用sparkSession连接数据,并在数据库执行sql,在idea展示执行结果。 但是,如果将数据的查询结果建立到spark中,再展示,就会报错 Error while run…...
在一个循环链队中只有尾指针(记为rear,结点结构为数据域data,指针域next),请给出这种队列的入队和出队操作实现过程
在一个循环链队中只有尾指针(记为rear,结点结构为数据域data,指针域next),请给出这种队列的入队和出队操作实现过程 入队过程如下图: 先创一个结点,用于存储要插入的结点数据 然后就是老套路了…...
智能客服系统应用什么技术?
随着科技的飞速发展,智能客服系统逐渐出现在我们的生活中。这些系统不仅能够提供即时的客户服务,还可以通过人工智能等技术实现更加高效和准确的服务。那么,智能客服系统究竟应用了哪些技术呢?本文将详细解析。 1、机器学习技术 …...
亚马逊、美客多卖家测评:如何建立养号团队实现运营化式测评?
大家好,我是跨境电商测评养号7年从事经验的珑哥。养号环境软件开发,深度解决各跨境平台矩阵养号防关联、砍单、F号问题。关注珑哥解决更多跨境养号测评问题。 测评,相信这个词对于大部分跨境卖家来说,想必都不陌生,因…...
苹果IOS系统webglcontextlost问题-解决方案
问题描述 在IOS手机 解码视频流的时候,第一次可以正常播放,但只要IOS手机熄屏,再重新唤醒,就会一直播放失败,无论换哪个浏览器都不行。安卓手机则一切正常。 经过排查,发现 IOS手机 的浏览器会无故 webGL…...
供应链ERP之合同:创建、修订与模板
本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…...
MySQL第二讲·表的创建与修改
你好,我是安然无虞。 文章目录 表:怎么创建和修改数据表?1. 如何创建数据表?2. 都有哪些约束?3. 如何修改表?添加字段修改字段 表:怎么创建和修改数据表? 创建和修改数据表&#x…...
springboot的循环依赖问题描述及解决方案
一.了解循环依赖的场景 在Spring Boot中,循环依赖是指两个或多个Bean之间相互依赖,导致它们无法正确地创建和注入。循环依赖可能会导致应用程序无法启动或出现其他异常。 在以下情况下,您可能需要显式设置循环依赖: 两个Bean相…...
当科技遇上神器:用Streamlit定制AI可视化问答界面
Streamlit是一个开源的Python库,利用Streamlit可以快速构建机器学习应用的用户界面。 本文主要探讨如何使用Streamlit构建大模型外部知识检索的AI问答可视化界面。 我们先构建了外部知识检索接口,然后让大模型根据检索返回的结果作为上下文来回答问题。…...
毛泽东思想和中国特色社会主义理论概论平时作业四
毛泽东思想和中国特色社会主义理论概论平时作业四 1.单选题 1.1人民代表大会制度是中国人民当家作主的基本政治制度,是我国的国体。(b) a.正确 b.错误 人民代表大会制度是中国人民当家作主的根本政治制度,是我国的政体。1.2我国的政体是人民民主专政。…...
微信怎么设置自动通过好友申请?
当开展引流获客活动时,员工会在一段时间内频繁收到好友添加的申请,手动同意好友请求费时费力还容易出现漏加的情况,那么微信能自动通过好友请求吗? 如何设置快速自动通过好友申请呢? 当微信号在系统登录,…...
亲测解决Pytorch TypeError: object of type ‘numpy.int64‘ has no len()
这个问题是小虎在初始化自适应平均池化的时候遇到的,解决方法是限制初始化时池化大小的类型。 问题原文 Exception has occurred: TypeError object of type numpy.int64 has no len()File "D:\Complier\LEF\lib\model\segmentation\heads\modules\fgModules…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
