[Tech Blog] 복수 AWS계정의 NAT Gateway를 ‘VPC Peering+Proxy’로 중앙 집약 시키기

들어가며


보통 각 AWS 계정에 Nat Gateway를 배치하고 외부 통신을 진행 하는 경우가 많으실 듯 합니다.

그러나 여러 AWS 계정을 관리하고 있고 각각에 Nat Gateway가 필요한 경우, 총 비용이 많이 발생하게 됩니다.

그에 대한 해결책으로 중앙 VPC를 준비해, 각 계정의 통신을 집약시키는 구성을 짜 본 내용에 대해 공유 드리고자 합니다. (프록시가 중복되지 않는 문제는 별도로 해결해야 하지만 우선 기본 구성으로 진행 하겠습니다.)




전제

– AWS 계정 3개
– Terraform 사용




목차

1. 중앙 네트워크 구축
2. 하위 네트워크 구축
3. VPC Peering 설정
4. Proxy 설정
5. 연결 테스트




1. 중앙 네트워크 구축

중앙 계정의 디렉토리 구조는 다음과 같습니다.


% tree
.
├── compute.tf
├── network.tf
└── variables.tf


network.tf

resource "aws_vpc" "central_vpc" {
    cidr_block                       = "${var.vpc_range}"
    enable_dns_support               = true
    tags                             = {
        "Name"    = "${var.tenant}-central-vpc"
    }
}

resource "aws_subnet" "sub_pub1" {
    availability_zone                              ="ap-northeast-1a"
    cidr_block                                     ="${var.pub_sub1_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pub1"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
}

resource "aws_subnet" "sub_pub2" {
    availability_zone                              ="ap-northeast-1c"
    cidr_block                                     ="${var.pub_sub2_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pub2"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
}

resource "aws_subnet" "sub_pri1" {
    availability_zone                              ="ap-northeast-1a"
    cidr_block                                     ="${var.pri_sub1_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pri1"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
}

resource "aws_subnet" "sub_pri2" {
    availability_zone                              ="ap-northeast-1c"
    cidr_block                                     ="${var.pri_sub2_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pri2"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
}

resource "aws_internet_gateway" "igw" {
    tags                                           = {
        "Name" = "${var.tenant}-igw"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"

}

resource "aws_eip" "eip" {
    tags                                           = {
        "Name" = "${var.tenant}-eip"
    }
}

resource "aws_nat_gateway" "ngw" {
    tags                                           = {
        "Name" = "${var.tenant}-ngw"
    }
    subnet_id                                      ="${aws_subnet.sub_pub1.id}"
    allocation_id                                  ="${aws_eip.eip.id}"
    connectivity_type                              ="public"
}

resource "aws_route_table" "rtb_pub" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pub"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        gateway_id                                 ="${aws_internet_gateway.igw.id}"
    }
}

resource "aws_route_table" "rtb_pri1" {
    tags                                           = {
        "Name" = "rtb-pri1"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        nat_gateway_id                             ="${aws_nat_gateway.ngw.id}"
    }
/*
    route {
        cidr_block                = "${var.peering_vpc_cidr1}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central1.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr2}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central2.id}"
    }
*/
}

resource "aws_route_table" "rtb_pri2" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri2"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        nat_gateway_id                             ="${aws_nat_gateway.ngw.id}"
    }
/*
    route {
        cidr_block                = "${var.peering_vpc_cidr1}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central1.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr2}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central2.id}"
    }
*/
}

resource "aws_route_table_association" "public_rt_1a" {
  subnet_id      = aws_subnet.sub_pub1.id
  route_table_id = aws_route_table.rtb_pub.id
}

resource "aws_route_table_association" "public_rt_1c" {
  subnet_id      = aws_subnet.sub_pub2.id
  route_table_id = aws_route_table.rtb_pub.id
}

resource "aws_route_table_association" "private_rt_1a" {
  subnet_id      = aws_subnet.sub_pri1.id
  route_table_id = aws_route_table.rtb_pri1.id
}

resource "aws_route_table_association" "private_rt_1c" {
  subnet_id      = aws_subnet.sub_pri2.id
  route_table_id = aws_route_table.rtb_pri2.id
}

resource "aws_vpc_endpoint" "vpc_ep_s3" {
    tags                                           = {
        "Name" = "${var.tenant}-vpc-ep-s3"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    vpc_endpoint_type                              ="Gateway"
    service_name                                   ="com.amazonaws.ap-northeast-1.s3"
    route_table_ids = [
        "${aws_route_table.rtb_pri1.id}",
        "${aws_route_table.rtb_pri2.id}"
    ]
}

/*
resource "aws_vpc_peering_connection" "vpc_connection_from_central1" {
  peer_owner_id = "${var.accepter_account1}"
  peer_vpc_id = "${var.peering_vpc_id1}"
  vpc_id      = "${aws_vpc.central_vpc.id}"
}

resource "aws_vpc_peering_connection" "vpc_connection_from_central2" {
  peer_owner_id = "${var.accepter_account2}"
  peer_vpc_id = "${var.peering_vpc_id2}"
  vpc_id      = "${aws_vpc.central_vpc.id}"
}
*/



compute.tf

data aws_ssm_parameter amzn2_ami {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}

data "aws_iam_policy_document" "proxy_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "proxy_role" {
  name               = "${var.tenant}-ec2-role"
  assume_role_policy = data.aws_iam_policy_document.proxy_assume_role.json
}

data "aws_iam_policy" "ssm_instance_core" {
  arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_role_policy_attachment" "default" {
  role       = aws_iam_role.proxy_role.name
  policy_arn = data.aws_iam_policy.ssm_instance_core.arn
}

resource "aws_iam_instance_profile" "proxy_profile" {
  name = "InstanceProfile"
  role = aws_iam_role.proxy_role.name
}

resource "aws_security_group" "proxy_sg" {
  name        = "${var.tenant}-ec2-sg"
  vpc_id      = aws_vpc.central_vpc.id
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${var.tenant}-ec2-sg"
  }
}

resource "aws_instance" "proxy" {
  ami                  = data.aws_ssm_parameter.amzn2_ami.value
  instance_type        = "t3.micro"
  iam_instance_profile = aws_iam_instance_profile.proxy_profile.name
  subnet_id            = aws_subnet.sub_pri1.id
  vpc_security_group_ids      = [aws_security_group.proxy_sg.id]
  lifecycle {
    ignore_changes = [
      ami,
    ]
  }
}



variables.tf
//환경 고유명
variable "tenant" {
  default = "test"
}

//리전
variable "region" {
  default = "ap-northeast-1"
}

//중앙VPC의 CIDR
variable "vpc_range" {
  default = "10.1.0.0/16"
}

//중앙 퍼블릭 서브넷 CIDR
variable "pub_sub1_range" {
  default = "10.1.0.0/24"
}

//중앙 퍼블릭 서브넷 CIDR
variable "pub_sub2_range" {
  default = "10.1.1.0/24"
}

//중앙 프라이빗 서브넷 CIDR
variable "pri_sub1_range" {
  default = "10.1.2.0/24"
}

//중앙 프라이빗 서브넷 CIDR
variable "pri_sub2_range" {
  default = "10.1.3.0/24"
}

/*
//계정 A의 계정 ID
variable "accepter_account1" {
  default = "xxxxxxxxxxxx"
}

//계정B의 계정 ID
variable "accepter_account2" {
  default = "xxxxxxxxxxxx"
}

//계정 A의 VPC ID
variable "peering_vpc_id1" {
  default = "xxxxxxxxxxxx"
}

//계정 A의 VPC CIDR
variable "peering_vpc_cidr1" {
  default = "10.2.0.0/16"
}

//계정 B의 VPC ID
variable "peering_vpc_id2" {
  default = "xxxxxxxxxxxx"
}

//계정 B의 VPC CIDR
variable "peering_vpc_cidr2" {
  default = "10.3.0.0/16"
}
*/


위의 디플로이는 다음을 디플로이 합니다.
variables.tf는 VPC의 CIDR 등을 지정하므로 환경에 맞게 기본값을 넣으세요.
※Preering관련해서는 일단 코멘트 하지 않겠습니다.


– 중앙 계정 VPC 및 네트워크 리소스
– NAT Gateway
– EC2(Proxy)




2. 하위 네트워크 구축

중앙 계정에 연결하는 하위 계정 측에 디플로이합니다.

디렉토리 구조는 다음과 같습니다.
variables.tf의 값은 각각 환경에 맞게 변경하세요.


.
├── connection-test.tf
├── network.tf
└── variables.tf


network.tf

resource "aws_vpc" "account_vpc" {
    cidr_block                       = "${var.vpc_range}"
    enable_dns_support               = true
    enable_dns_hostnames             = true
    tags                             = {
        "Name"    = "${var.tenant}-vpc"
    }
}

resource "aws_subnet" "sub_pub1" {
    availability_zone                              ="ap-northeast-1a"
    cidr_block                                     ="${var.pub_sub1_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pub1"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
}

resource "aws_subnet" "sub_pub2" {
    availability_zone                              ="ap-northeast-1c"
    cidr_block                                     ="${var.pub_sub2_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pub2"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
}

resource "aws_subnet" "sub_pri1" {
    availability_zone                              ="ap-northeast-1a"
    cidr_block                                     ="${var.pri_sub1_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pri1"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
}

resource "aws_subnet" "sub_pri2" {
    availability_zone                              ="ap-northeast-1c"
    cidr_block                                     ="${var.pri_sub2_range}"
    tags                                           = {
        "Name" = "${var.tenant}-subnet-pri2"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
}

resource "aws_internet_gateway" "igw" {
    tags                                           = {
        "Name" = "${var.tenant}-igw"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
}

resource "aws_route_table" "rtb_pub" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pub"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        gateway_id                                 ="${aws_internet_gateway.igw.id}"
    }
}

resource "aws_route_table" "rtb_pri1" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri1"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
/*
    route {
        cidr_block                = "${var.peering_vpc_cidr}"
        vpc_peering_connection_id = "${var.vpc_connection_id}"
    }
*/
}

resource "aws_route_table" "rtb_pri2" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri2"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
/*
    route {
        cidr_block                = "${var.peering_vpc_cidr}"
        vpc_peering_connection_id = "${var.vpc_connection_id}"
    }
*/
}

resource "aws_route_table_association" "public_rt_1a" {
  subnet_id      = aws_subnet.sub_pub1.id
  route_table_id = aws_route_table.rtb_pub.id
}

resource "aws_route_table_association" "public_rt_1c" {
  subnet_id      = aws_subnet.sub_pub2.id
  route_table_id = aws_route_table.rtb_pub.id
}

resource "aws_route_table_association" "private_rt_1a" {
  subnet_id      = aws_subnet.sub_pri1.id
  route_table_id = aws_route_table.rtb_pri1.id
}

resource "aws_route_table_association" "private_rt_1c" {
  subnet_id      = aws_subnet.sub_pri2.id
  route_table_id = aws_route_table.rtb_pri2.id
}

resource "aws_vpc_endpoint" "vpc_ep_s3" {
    tags                                           = {
        "Name" = "${var.tenant}-vpc-ep-s3"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
    vpc_endpoint_type                              ="Gateway"
    service_name                                   ="com.amazonaws.ap-northeast-1.s3"
    route_table_ids = [
        "${aws_route_table.rtb_pri1.id}",
        "${aws_route_table.rtb_pri2.id}"
    ]
}



connection-test.tf

resource "aws_vpc_endpoint" "ssm" {
  vpc_id              = aws_vpc.account_vpc.id
  service_name        = "com.amazonaws.${var.region}.ssm"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  subnet_ids          = [aws_subnet.sub_pri1.id]
  private_dns_enabled = true
}
 
resource "aws_vpc_endpoint" "ec2messages" {
  vpc_id              = aws_vpc.account_vpc.id
  service_name        = "com.amazonaws.${var.region}.ec2messages"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  subnet_ids          = [aws_subnet.sub_pri1.id]
  private_dns_enabled = true
}
 
resource "aws_vpc_endpoint" "ssmmessages" {
  vpc_id              = aws_vpc.account_vpc.id
  service_name        = "com.amazonaws.${var.region}.ssmmessages"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  subnet_ids          = [aws_subnet.sub_pri1.id]
  private_dns_enabled = true
}

resource "aws_security_group" "vpc_endpoint_sg" {
  name   = "${var.tenant}-vpc-endpoint-sg"
  vpc_id = aws_vpc.account_vpc.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "main" {
  name   = "${var.tenant}-sg"
  vpc_id = aws_vpc.account_vpc.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

data "aws_ami" "latest_amazon_linux2" {
  most_recent = true
  owners      = ["amazon"]
 
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "main" {
  instance_type          = "t3.micro"
  ami                    = data.aws_ami.latest_amazon_linux2.id
  subnet_id              = aws_subnet.sub_pri1.id
  vpc_security_group_ids = [aws_security_group.main.id]
  iam_instance_profile   = aws_iam_instance_profile.test_profile.name
  root_block_device {
    volume_size           = 8
    volume_type           = "gp3"
    iops                  = 3000
    throughput            = 125
  }
  lifecycle {
    ignore_changes = [
      ami,
    ]
  }
}

resource "aws_iam_instance_profile" "test_profile" {
  name = "${var.tenant}-ssm"
  role = aws_iam_role.ssm_role.name
}
 
resource "aws_iam_role" "ssm_role" {
  name               = "${var.tenant}-ssm"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
 
data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
 
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}
 
resource "aws_iam_role_policy_attachment" "ssm_managed_instance_core" {
  role       = aws_iam_role.ssm_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}


variables.tf

variable "tenant" {
  default = "accounta"
}

variable "region" {
  default = "ap-northeast-1"
}

variable "vpc_range" {
  default = "10.5.0.0/16"
}

variable "pub_sub1_range" {
  default = "10.5.0.0/24"
}

variable "pub_sub2_range" {
  default = "10.5.1.0/24"
}

variable "pri_sub1_range" {
  default = "10.5.2.0/24"
}

variable "pri_sub2_range" {
  default = "10.5.3.0/24"
}

/*
variable "peering_vpc_cidr" {
  default = "10.1.0.0/16"
}

variable "vpc_connection_id" {
  default = "xxxxxxxxxxxxxxxx"
}
*/



위의 디플로이는 다음을 디플로이 합니다.
variables.tf는 VPC의 CIDR 등을 지정하므로 환경에 맞게 기본값을 넣으세요.
※Preering관련해서는 일단 코멘트 하지 않겠습니다.


– 각 계정의 VPC 및 네트워크 리소스
– EC2(연결 확인 필요)
※중앙 계정측의 NAT Gateway를 경유해 인터넷에 접속되기 때문에 하위 계정측에 NAT Gateway는 배치하지 않습니다.


이번 검증에서는 2개의 AWS 계정에 배포합니다.

CIDR은 중앙 계정/각 계정 사이에 걸리지 않아야 합니다.




3. VPC Peering 설정


그런 후 VPC Peering을 설정합니다.




//중앙 계정



중앙 계정의 각 TF 파일에 대해 아래의 코멘트 아웃을 제거하고 필요한 설정을합니다.




variables.tf


//계정 A의 계정ID
variable "accepter_account1" {
  default = "xxxxxxxxxxxx" //하위 계정 1의 AWS 계정 ID 입력
}

//계정 B의 계정 ID
variable "accepter_account2" {
  default = "xxxxxxxxxxxx" //하위 계정 2의 AWS 계정 ID 입력
}

//계정 A의 VPC ID
variable "peering_vpc_id1" {
  default = "xxxxxxxxxxxx" //하위 계정 1의 VPC ID 입력
}

//계정 A의 VPC CIDR
variable "peering_vpc_cidr1" {
  default = "10.2.0.0/16" //하위 계정 1의 VPC CIDR 입력
}

//계정 B의 VPC ID
variable "peering_vpc_id2" {
  default = "xxxxxxxxxxxx" //하위 계정 2의 VPC ID 입력 
}

//계정 B의 VPC CIDR
variable "peering_vpc_cidr2" {
  default = "10.3.0.0/16" //하위 계정 2의 VPC CIDR 입력
}


network.tf

resource "aws_route_table" "rtb_pri1" {
    tags                                           = {
        "Name" = "rtb-pri1"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        nat_gateway_id                             ="${aws_nat_gateway.ngw.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr1}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central1.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr2}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central2.id}"
    }
}

resource "aws_route_table" "rtb_pri2" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri2"
    }
    vpc_id                                         ="${aws_vpc.central_vpc.id}"
    route {
        cidr_block                                 ="0.0.0.0/0"
        nat_gateway_id                             ="${aws_nat_gateway.ngw.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr1}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central1.id}"
    }
    route {
        cidr_block                = "${var.peering_vpc_cidr2}"
        vpc_peering_connection_id = "${aws_vpc_peering_connection.vpc_connection_from_central2.id}"
    }
}

resource "aws_vpc_peering_connection" "vpc_connection_from_central1" {
  peer_vpc_id = "${var.peering_vpc_id1}"
  vpc_id      = "${aws_vpc.central_vpc.id}"
  auto_accept = true
}

resource "aws_vpc_peering_connection" "vpc_connection_from_central2" {
  peer_vpc_id = "${var.peering_vpc_id2}"
  vpc_id      = "${aws_vpc.central_vpc.id}"
  auto_accept = true
}


위의 디플로이(변경) 결과, VPC 페이지의 “Peering connections”에 설정이 나타납니다.





다음으로 하위 계정 측의 Peering connections 페이지로 이동하여 Accept request를 수행합니다.





중앙 계정 -2 계정 간의 피어링이 Active 상태인지 확인합니다.




// 하위 계정 측



variables.tf

variable "peering_vpc_cidr" {
  default = "10.1.0.0/16" //중앙 계정의 VPC CIDR
}

variable "vpc_connection_id" {
  default = "xxxxxxxxxxxxxxxx" //Peering Connection ID
}




network.tf

resource "aws_route_table" "rtb_pri1" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri1"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
    route {
        cidr_block                = "${var.peering_vpc_cidr}"
        vpc_peering_connection_id = "${var.vpc_connection_id}"
    }
}

resource "aws_route_table" "rtb_pri2" {
    tags                                           = {
        "Name" = "${var.tenant}-rtb-pri2"
    }
    vpc_id                                         ="${aws_vpc.account_vpc.id}"
    route {
        cidr_block                = "${var.peering_vpc_cidr}"
        vpc_peering_connection_id = "${var.vpc_connection_id}"
    }
}


VPC 피어링 설정과 루트 설정이 완료되었습니다.




4. Proxy 설정


지금 상태로는 하위 계정 ~ 중앙 계정의 Nat Gateway를 경유한 외부 통신이 불가능하기 때문에 중앙 계정의 EC2에 Squid 설정을 넣겠습니다.





중앙 계정의 AWS Management Console에 로그인합니다.
Proxy 서버의 Session Manager로 들어갑니다.


//Squid 설치 & conf 파일 만들기

$ sudo yum update -y
$ sudo yum install squid -y
$ sudo touch /etc/squid/squid.conf

// etc/squid/squid.conf 편집



acl localnet src 10.2.0.0/16 //하위 계정 측에 맞춤
acl localnet src 10.3.0.0/16 //하위 계정 측에 맞춤   

acl Safe_ports port 80          # http
acl Safe_ports port 443         # https
http_access deny !Safe_ports

acl SSL_ports port 443          # https
acl CONNECT method CONNECT
http_access deny CONNECT !SSL_ports

# 화이트리스트 지정
acl whitelist dstdomain "/etc/squid/whitelist"

http_access deny !localnet

http_access allow whitelist

http_access deny all

http_port 3128

no_cache deny all

coredump_dir /var/spool/squid

logformat squid %tl %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt

visible_hostname unknown

forwarded_for off
request_header_access User-Agent deny all
request_header_access Referer deny all
request_header_access X-Forwarded-For deny all
request_header_access Via deny all
request_header_access Cache-Control deny all


설정 파일을 업데이트합니다.

$ sudo systemctl start squid
$ sudo systemctl enable squid



Squid의 기동 정지를 실시합니다.

$ sudo touch /etc/squid/whitelist


그 후 화이트리스트를 설정합니다.


//etc/squid/whitelist

.google.com


테스트로 google.com을 지정 했습니다.

$ sudo chmod 644 /etc/squid/whitelist
$ sudo chown squid:squid /etc/squid/whitelist

$ sudo systemctl reload squid



다시 로드합니다.




마지막으로 EC2 (proxy) 보안 그룹을 환경에 맞게 설정하세요.




5.  연결 테스트


하위 계정 1의 EC2에 대해 Session Manager에 로그인합니다.



ping ※프록시 서버의 IP주소


우선 중앙 계정의 Proxy 서버에 연결 확인을 합니다.
EC2 (Proxy)의 프라이빗 IP 주소를 지정하세요.


연결이 가능한지 확인합니다.
통신이 불가능한 경우 Proxy 보안 그룹 설정 등을 확인하시길 바랍니다.

$ export http_proxy=http://10.1.2.49:3128 //프록시 서버의 ip주소 입력
$ export https_proxy=http://10.1.2.49:3128 //프록시 서버의 ip주소 입력

$ curl -I https://www.google.com //화이트리스트로 허가
HTTP/1.1 200 Connection established

$ curl -I https://www.amazon.com //화이트리스트에 기재 없음
HTTP/1.1 403 Forbidden




– google.com에 액세스할 수 있는 작업
– 그 이외는 거부될 것


상기의 내용을 확인합니다.
예상대로 움직이는 것을 확인 하였습니다.

하위 계정 2에 대해서도 마찬가지로 연결 테스트를 실시하여 연결 되는지 확인하세요.




끝으로

별도로 Proxy 서버의 다중화 구조에 대해서는 추후 블로그로 써 보고자 생각 하고 있습니다. 업무하시면서 참고가 되신다면 좋을 것 같습니다.


여기까지 읽어주셔서 감사합니다.


작성자 : Megazone Japan / Aga Hiroaki
원문 게시글 : https://zenn.dev/megazone_jp/articles/aedb4f18ed7711
번역 : 메가존클라우드 Cloud Technology Center 박지은 매니저

게시물 주소가 복사되었습니다.