AWS Builder Center
AWS Session Manager Port Forwarding to Remote Host

AWS Session Manager Port Forwarding to Remote Host

O AWS Systems Manager Session Manager permite criar sessões de port forwarding entre uma máquina local e recursos privados acessíveis através de uma instância EC2 gerenciada pelo Systems Manager. Esse recurso permite acessar aplicações, bancos de dados e outros serviços executados dentro de uma rede privada sem a necessidade de expor esses recursos para a internet ou possuir conectividade de rede direta entre o computador do usuário e o recurso de destino.

O AWS Systems Manager Session Manager permite criar sessões de port forwarding entre uma máquina local e recursos privados acessíveis através de uma instância EC2 gerenciada pelo Systems Manager.
Esse recurso permite acessar aplicações, bancos de dados e outros serviços executados dentro de uma rede privada sem a necessidade de expor esses recursos para a internet ou possuir conectividade de rede direta entre o computador do usuário e o recurso de destino.
Neste projeto, utilizaremos uma instância EC2 em uma subnet privada como ponto intermediário para acessar um Amazon RDS PostgreSQL também privado.
1
Notebook localhost:5432 -> AWS Systems Manager -> SSM Agent -> EC2 -> RDS PostgreSQL:5432
Nesse modelo, tanto a EC2 quanto o RDS podem permanecer sem acesso público.
A comunicação entre nossa máquina e a EC2 é transportada através de uma sessão do AWS Systems Manager. A partir da EC2, a conexão com o RDS utiliza a conectividade privada existente dentro da VPC.

EC2 em subnet privada

A instância EC2 utilizada neste projeto será executada em uma subnet privada.
Uma subnet privada não possui rota direta para um Internet Gateway. Dessa forma, a instância não precisa possuir endereço IP público e não pode receber conexões iniciadas diretamente através da internet.
A Route Table associada à subnet privada utiliza um NAT Gateway para permitir conexões de saída:
1
2
10.0.0.0/16 -> local
0.0.0.0/0 -> NAT Gateway
O NAT Gateway fica localizado em uma subnet pública e possui conectividade com a internet através do Internet Gateway.
A comunicação de saída da instância acontece da seguinte forma:
1
EC2 privada -> NAT Gateway -> Internet Gateway -> Internet
No caso do Session Manager, o SSM Agent inicia a comunicação HTTPS necessária com a infraestrutura da AWS. O NAT Gateway fornece o caminho de saída necessário para essa comunicação.
Isso não torna a EC2 acessível através da internet. A instância continua privada e sem a necessidade de possuir regras de entrada para permitir o acesso através do Session Manager.

Amazon RDS em subnet privada

O Amazon RDS PostgreSQL utilizado neste projeto também será executado de forma privada dentro da VPC.
O banco não precisa possuir acesso público porque nossa máquina não estabelecerá uma conexão diretamente com o endpoint do RDS.
Não teremos:
1
Notebook -> Internet -> RDS:5432
O acesso ao banco acontecerá através da conectividade existente entre a EC2 e o RDS:
1
EC2 -> RDS PostgreSQL:5432
Por isso, nossa máquina não precisa possuir rota para as subnets privadas onde o banco está localizado.
O requisito de rede existe entre a EC2 e o RDS.

Session Manager Port Forwarding to Remote Host

O Session Manager permite encaminhar uma porta da nossa máquina para um host remoto acessível através da instância EC2 utilizada como target da sessão.
Para isso, podemos utilizar o documento:
1
AWS-StartPortForwardingSessionToRemoteHost
Nesse modelo temos:
1
localhost:<LOCAL_PORT> -> Session Manager -> SSM Agent -> EC2 -> <REMOTE_HOST>:<REMOTE_PORT>
A EC2 funciona como o managed node da sessão e precisa possuir conectividade de rede com o remote host.
Neste projeto, o remote host será o endpoint privado de um RDS PostgreSQL:
1
localhost:5432 -> Session Manager -> SSM Agent -> EC2 -> RDS PostgreSQL:5432
O notebook não estabelece uma conexão TCP diretamente com o endereço privado da EC2 ou com o RDS.
O Session Manager transporta a comunicação até a instância e, a partir dela, a rede da VPC é utilizada para alcançar o banco.

Criando a sessão de Port Forwarding

Para criar a sessão podemos utilizar:
1
2
3
4
5
6
7
8
9
10
aws ssm start-session \
--target <INSTANCE_ID> \
--region <AWS_REGION> \
--profile <PROFILE> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{
"host":["<REMOTE_HOST>"],
"portNumber":["<REMOTE_PORT>"],
"localPortNumber":["<LOCAL_PORT>"]
}'

Existem três parâmetros importantes nesse comando.
host representa o hostname ou endereço do recurso remoto que será acessado através da EC2.
portNumber representa a porta utilizada pelo serviço no remote host.
localPortNumber representa a porta que ficará disponível na nossa máquina.
Para um RDS PostgreSQL podemos utilizar:
1
2
3
4
5
6
7
8
9
10
aws ssm start-session \
--target i-0123456789abcdef0 \
--region us-east-1 \
--profile <PROFILE> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{
"host":["database.xxxxxxxxxxxx.us-east-1.rds.amazonaws.com"],
"portNumber":["5432"],
"localPortNumber":["5432"]
}'

Nesse cenário:
1
localhost:5432 -> EC2 -> RDS PostgreSQL:5432
A porta local não precisa ser igual à porta utilizada pelo recurso remoto.
Também poderíamos utilizar:
1
localhost:15432 -> RDS PostgreSQL:5432
configurando:
1
2
3
4
5
{
"host": ["database.xxxxxxxxxxxx.us-east-1.rds.amazonaws.com"],
"portNumber": ["5432"],
"localPortNumber": ["15432"]
}
Nesse caso, nosso cliente PostgreSQL utilizaria:
1
localhost:15432
enquanto o RDS continuaria recebendo a conexão na porta 5432.

Como o tráfego chega até o RDS

Quando a sessão de port forwarding está ativa, o Session Manager Plugin passa a escutar a porta definida em localPortNumber na nossa máquina.
No nosso exemplo:
1
localhost:5432
Quando uma aplicação como DBeaver ou psql conecta nessa porta, o tráfego é recebido pelo Session Manager Plugin e transportado através da sessão do Systems Manager até o SSM Agent executado na EC2.
O SSM Agent então encaminha a comunicação para o host e porta definidos na sessão:
1
database.xxxxxxxxxxxx.us-east-1.rds.amazonaws.com:5432
A partir desse ponto, a EC2 utiliza sua própria conectividade de rede para alcançar o RDS.
Podemos representar o fluxo completo como:
1
DBeaver -> localhost:5432 -> Session Manager Plugin -> AWS Systems Manager -> SSM Agent -> EC2 -> RDS:5432
A resposta do PostgreSQL percorre o caminho contrário até chegar novamente ao cliente local.
Por isso conseguimos utilizar localhost:5432 mesmo que o banco esteja localizado em uma subnet privada e nossa máquina não possua uma rota até ele.

Resolução do endpoint do RDS

O endpoint informado no parâmetro host precisa ser alcançável a partir da instância EC2.
No nosso cenário:
1
EC2 -> database.xxxxxxxxxxxx.us-east-1.rds.amazonaws.com:5432
A EC2 precisa conseguir resolver o endpoint do RDS e possuir conectividade de rede com os endereços retornados.
Nossa máquina não precisa estabelecer essa conexão diretamente.
O fluxo continua sendo:
1
Notebook -> localhost:5432 -> Session Manager -> EC2 -> RDS endpoint:5432
Por isso o requisito de conectividade existe entre:
1
EC2 -> RDS
e não entre:
1
Notebook -> RDS

Security Groups

Os Security Groups possuem responsabilidades importantes nessa arquitetura.
A EC2 não precisa possuir uma regra de entrada permitindo conexões do nosso notebook para a porta 5432.
Também não precisamos liberar SSH para acessar a instância:
1
EC2 Inbound TCP 22 -> 0.0.0.0/0
A sessão é estabelecida através do AWS Systems Manager.
Entretanto, existe uma conexão de rede entre a EC2 e o RDS:
1
EC2 -> RDS:5432
Por isso, o Security Group do RDS precisa permitir conexões TCP na porta 5432 originadas pelo Security Group utilizado pela EC2.
1
2
3
RDS Security Group

Inbound TCP 5432 <- EC2 Security Group
Esse modelo permite controlar a comunicação utilizando a identidade do Security Group da EC2 em vez de liberar o banco para uma faixa de endereços externa.
Não precisamos configurar:
1
RDS Inbound TCP 5432 <- 0.0.0.0/0
O RDS continua privado e aceita a conexão necessária através da rede da VPC.

A EC2 como ponto intermediário

A instância EC2 funciona como o ponto intermediário entre a sessão do Systems Manager e o recurso privado.
Ela não precisa executar PostgreSQL, DBeaver ou qualquer aplicação relacionada ao banco.
Ela precisa estar configurada como managed node do Systems Manager e possuir conectividade de rede com o remote host.
1
Notebook -> AWS Systems Manager -> EC2 -> Remote Host
No nosso projeto:
1
Notebook -> AWS Systems Manager -> EC2 privada -> RDS PostgreSQL privado
O remote host também não precisa necessariamente ser um RDS.
O mesmo modelo pode ser utilizado para outros serviços TCP privados que sejam alcançáveis pela EC2.

Acessando o PostgreSQL com psql

Com a sessão ativa, podemos utilizar um cliente PostgreSQL instalado na nossa própria máquina.
1
2
3
4
5
psql \
--host localhost \
--port 5432 \
--username <DB_USER> \
--dbname <DB_NAME>
Para o psql, o banco está disponível através de:
1
localhost:5432
O cliente não precisa conhecer o endereço privado da EC2 e nem possuir conectividade direta com o endpoint do RDS.
A comunicação é transportada através da sessão até a EC2 e encaminhada para o banco.

Acessando o PostgreSQL com DBeaver

Também podemos utilizar o DBeaver para acessar o banco.
Enquanto a sessão estiver ativa, podemos configurar:
1
2
3
4
5
Host: localhost
Port: 5432
Database: <DB_NAME>
Username: <DB_USER>
Password: <DB_PASSWORD>
O DBeaver abre uma conexão TCP para:
1
localhost:5432
O Session Manager Plugin recebe essa conexão e transporta o tráfego através da sessão:
1
DBeaver -> localhost:5432 -> Session Manager Plugin -> AWS Systems Manager -> SSM Agent -> EC2 -> RDS:5432
Para o DBeaver, estamos conectando em um PostgreSQL disponível localmente.
O banco, entretanto, continua executando de forma privada dentro da AWS.

Port Forwarding não torna o RDS público

Criar uma sessão utilizando AWS-StartPortForwardingSessionToRemoteHost não altera a configuração de rede do RDS.
O banco continua privado.
Não criamos:
1
Internet -> RDS:5432
Também não transformamos o endpoint privado em um endpoint público.
O caminho existe enquanto a sessão estiver ativa:
1
localhost:5432 -> Session Manager -> EC2 -> RDS:5432
Quando a sessão é encerrada, a porta local deixa de fornecer esse caminho até o banco.
O RDS continua funcionando normalmente dentro da VPC.

Arquitetura

A infraestrutura utilizada neste projeto possui subnets públicas e privadas distribuídas entre duas Availability Zones.
A instância EC2 é executada em uma subnet privada, sem endereço IP público.
O Amazon RDS PostgreSQL também permanece privado e não recebe conexões diretamente da internet.
O NAT Gateway localizado na camada pública fornece conectividade de saída para que o SSM Agent alcance os endpoints públicos necessários do AWS Systems Manager.
O acesso ao banco acontece através do Session Manager Port Forwarding to Remote Host.
1
Notebook localhost:5432 -> AWS Systems Manager -> SSM Agent -> EC2 privada -> RDS PostgreSQL:5432
É importante separar os dois fluxos envolvidos nessa arquitetura.
A comunicação necessária para o SSM Agent alcançar o Systems Manager:
1
EC2 -> NAT Gateway -> Internet Gateway -> AWS Systems Manager
E a comunicação da EC2 com o banco:
1
EC2 -> Rede privada da VPC -> RDS PostgreSQL:5432
O NAT Gateway não transporta a conexão entre a EC2 e o RDS.
O Session Manager fornece o caminho entre nossa máquina e a instância. A partir da EC2, a conectividade privada da VPC fornece o caminho até o banco.

Comparação de arquitetura

Se o banco estivesse publicamente acessível, poderíamos ter:
1
Notebook -> Internet -> RDS Public Endpoint:5432
Nesse cenário, seria necessário fornecer conectividade pública ao banco e controlar quais origens poderiam acessar sua porta.
Uma arquitetura utilizando um bastion host e SSH poderia utilizar:
1
Notebook -> SSH -> Bastion Host -> RDS:5432
Com o Session Manager Port Forwarding to Remote Host:
1
Notebook localhost:5432 -> AWS Systems Manager -> SSM Agent -> EC2 privada -> RDS privado:5432
Não precisamos tornar o RDS publicamente acessível para permitir o acesso através da nossa máquina.
Também não precisamos expor a porta 22 da EC2 para criar um SSH tunnel.
A EC2 e o RDS podem permanecer privados enquanto o acesso é estabelecido através do AWS Systems Manager e da conectividade interna da VPC.

Conclusão

O AWS Systems Manager Session Manager permite utilizar Port Forwarding to Remote Host para acessar recursos privados que possuem conectividade com uma instância gerenciada pelo Systems Manager.
Nesse modelo, o Session Manager transporta o tráfego de uma porta local até a EC2 e, a partir dela, a conectividade da VPC é utilizada para alcançar o remote host.
1
localhost:<LOCAL_PORT> -> Session Manager -> SSM Agent -> EC2 -> <REMOTE_HOST>:<REMOTE_PORT>
Neste projeto, utilizamos uma EC2 privada como managed node para acessar um Amazon RDS PostgreSQL também privado.
1
DBeaver -> localhost:5432 -> Session Manager -> SSM Agent -> EC2 -> RDS PostgreSQL:5432
O banco não precisa possuir acesso público e nossa máquina não precisa possuir conectividade de rede direta com as subnets privadas da VPC.
A EC2 precisa apenas estar conectada ao Systems Manager e possuir conectividade de rede com o endpoint do RDS.
Dessa forma, conseguimos utilizar ferramentas locais como psql e DBeaver para acessar um PostgreSQL privado através do localhost, mantendo a EC2 e o banco isolados da internet e utilizando IAM e AWS Systems Manager para controlar o estabelecimento da sessão.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article