ExpressVPN이 웹 서버를 패치하고 안전하게 유지하는 방법

ExpressVPN 서버는 재에서 상승합니다.

이 기사에서는 ExpressVPN의 접근 방식에 대해 설명합니다. ExpressVPN 웹 사이트를 실행하는 인프라의 보안 패치 관리 (VPN 서버가 아님). 일반적으로 보안에 대한 우리의 접근 방식은 다음과 같습니다.

  1. 시스템을 매우 해킹하기 어렵다.
  2. 잠재적 피해 최소화 시스템이 가상으로 해킹 당하고 일부 시스템을 완벽하게 보호 할 수 없다는 사실을 인정하는 경우 일반적으로 아키텍처 설계 단계에서 시작하여 애플리케이션의 액세스를 최소화합니다..
  3. 시간을 최소화 시스템이 여전히 손상 될 수 있음.
  4. 확인 이러한 점은 내부 및 외부의 정기 검사로.

보안은 우리 문화에 뿌리를두고 있으며 모든 업무를 안내하는 주요 관심사입니다. 보안 소프트웨어 개발 관행, 응용 프로그램 보안, 직원 프로세스 및 교육 등과 같은 다른 많은 주제가 있지만이 게시물의 범위를 벗어납니다..

다음은 우리가 다음을 달성하는 방법을 설명합니다.

  1. 모든 서버가 완전히 패치되었는지 확인하십시오 CVE 간행물이 24 시간을 넘지 않아야합니다..
  2. 24 시간 이상 서버를 사용하지 않도록하십시오, 따라서 공격자가 지속성을 가질 수있는 시간의 상한을 설정.

우리는 OS 및 모든 최신 패치부터 서버를 재 구축하고 최소 24 시간마다 서버를 파괴하는 자동화 시스템.

이 기사의 목적은 유사한 문제에 직면 한 다른 개발자에게 유용하고 고객과 미디어에 ExpressVPN의 운영을 투명하게 제공하는 것입니다..

Ansible 플레이 북 및 Cloudformation 사용 방법

ExpressVPN의 웹 인프라는 전용 하드웨어에서 실행되는 VPN 서버와 달리 AWS에서 호스팅되며이 기능을 많이 사용하여 재구성이 가능합니다.

전체 웹 인프라에는 Cloudformation이 제공되며 최대한 많은 프로세스를 자동화하려고합니다. 그러나 원시 Cloudformation 템플릿으로 작업하는 것은 반복 필요성, 전반적인 가독성 저하 및 JSON 또는 YAML 구문의 제약으로 인해 매우 불쾌합니다..

이를 완화하기 위해 Ruby에서 템플릿 정의를 작성하고 JSON에서 Cloudformation 템플릿을 내보낼 수있는 cloudformation-ruby-dsl이라는 DSL을 사용합니다..

특히 DSL을 사용하면 자동으로 JSON으로 변환되는 일반 스크립트로 사용자 데이터 스크립트를 작성할 수 있습니다 (스크립트의 각 줄을 유효한 JSON 문자열로 만드는 힘든 과정을 거치지 않음).

cloudformation-infrastructure라는 일반적인 Ansible 역할은 실제 템플릿을 임시 파일로 렌더링 한 다음 cloudformation Ansible 모듈에서 사용합니다.

- 이름 : '렌더링 {{component}} 스택 cloudformation json'
셸 : '루비 "{{template_name | default (component)}}. rb" 확장 --stack-name {{stack}} --region {{aws_region}} > {{tempfile_path}} '
인수 :
chdir : ../cloudformation/templates
changed_when : 거짓

-이름 : '만들기 / 업데이트 {{component}} 스택'
클라우드 형성 :
stack_name : '{{stack}}-{{xv_env_name}}-{{구성 요소}}'
상태 : 현재
지역 : '{{aws_region}}'
템플릿 : '{{tempfile_path}}'
template_parameters : '{{template_parameters | 기본({}) }}'
stack_policy : '{{stack_policy}}'
레지스터 : cf_result

플레이 북에서는 여러 구성 요소 변수를 사용하여 cloudformation-infrastructure 역할을 여러 번 호출하여 여러 Cloudformation 스택을 만듭니다. 예를 들어 VPC 및 관련 리소스를 정의하는 네트워크 스택과 Auto Scaling 그룹, 시작 구성, 수명주기 후크 등을 정의하는 앱 스택이 있습니다..

그런 다음 다소 추악하지만 유용한 트릭을 사용하여 cloudformation 모듈의 출력을 후속 역할을위한 Ansible 변수로 변환합니다. Ansible에서는 동적 이름을 가진 변수를 만들 수 없으므로이 방법을 사용해야합니다.

- 포함 : _tempfile.yml
-복사 :
내용 : '{{구성 요소 | regex_replace ("-", "_")}} _ stack : {{cf_result.stack_outputs | to_json}} '
대상 : '{{tempfile_path}}. json'
no_log : true
changed_when : 거짓

-include_vars : '{{tempfile_path}}. json'

EC2 Auto Scaling 그룹 업데이트

ExpressVPN 웹 사이트는 Application Load Balancer 뒤의 Auto Scaling 그룹의 여러 EC2 인스턴스에서 호스팅되므로 인스턴스가 종료되기 전에로드 밸런서가 기존 연결을 소진 할 수 있기 때문에 다운 타임없이 서버를 제거 할 수 있습니다..

Cloudformation은 전체 재 구축을 오케스트레이션하고 AWS :: AutoScaling :: AutoScalingGroup 리소스의 AutoScalingRollingUpdate UpdatePolicy 속성을 사용하여 24 시간마다 위에서 설명한 Ansible 플레이 북을 트리거하여 모든 인스턴스를 재 구축합니다..

변경없이 단순히 반복적으로 트리거되는 경우 UpdatePolicy 속성이 사용되지 않으며 설명서에 설명 된 특수 상황에서만 호출됩니다. 이러한 상황 중 하나는 Auto Scaling 시작 구성 (Auto Scaling 그룹이 EC2 인스턴스를 시작하는 데 사용하는 템플릿)에 대한 업데이트입니다. 여기에는 새 인스턴스 생성시 실행되는 EC2 사용자 데이터 스크립트가 포함됩니다.

'AppLaunchConfiguration'리소스, 유형 : 'AWS :: AutoScaling :: LaunchConfiguration',
속성 : {
키 이름 : param ( 'AppServerKey'),
ImageId : param ( 'AppServerAMI'),
InstanceType : param ( 'AppServerInstanceType'),
보안 그룹 : [
param ( 'SecurityGroupApp'),
],
IamInstanceProfile : param ( 'RebuildIamInstanceProfile'),
인스턴스 모니터링 : true,
BlockDeviceMappings : [
{
장치 이름 : '/ dev / sda1', # 루트 볼륨
Ebs : {
VolumeSize : param ( 'AppServerStorageSize'),
VolumeType : param ( 'AppServerStorageType'),
DeleteOnTermination : true,
},
},
],
사용자 데이터 : base64 (interpolate (file ( 'scripts / app_user_data.sh'))),
}

사용자 데이터 스크립트, 주석까지 업데이트하면 시작 구성이 변경된 것으로 간주되며 Cloudformation은 새 시작 구성을 준수하도록 Auto Scaling 그룹의 모든 인스턴스를 업데이트합니다..

cloudformation-ruby-dsl 및 보간 유틸리티 기능 덕분에 app_user_data.sh 스크립트에서 Cloudformation 참조를 사용할 수 있습니다.

읽기 전용 rebuild_timestamp ="{{param ( 'RebuildTimestamp')}}"

이 절차는 재 구축이 트리거 될 때마다 시작 구성이 새로워 지도록합니다..

수명주기 후크

Auto Scaling 수명주기 후크를 사용하여 인스턴스가 완전히 프로비저닝되고 필요한 상태 확인이 통과되기 전에 전달합니다..

수명주기 후크를 사용하면 Cloudformation으로 업데이트를 트리거 할 때와 자동 스케일링 이벤트가 발생할 때 (예 : 인스턴스가 EC2 상태 확인에 실패하고 종료 될 때) 모두 동일한 인스턴스 수명주기를 가질 수 있습니다. cfn-signal 및 WaitOnResourceSignals 자동 스케일링 업데이트 정책은 Cloudformation이 업데이트를 트리거 할 때만 적용되므로 사용하지 않습니다..

자동 확장 그룹이 새 인스턴스를 생성하면 EC2_INSTANCE_LAUNCHING 수명주기 후크가 트리거되고 자동으로 인스턴스를 Pending : Wait 상태로 둡니다..

인스턴스가 완전히 구성되면 사용자 데이터 스크립트에서 curl을 사용하여 자체 상태 점검 엔드 포인트에 도달하기 시작합니다. 상태 확인에서 애플리케이션이 정상으로보고되면이 수명주기 후크에 대해 CONTINUE 조치를 발행하여 인스턴스가로드 밸런서에 연결되고 트래픽 제공을 시작합니다..

상태 확인에 실패하면 ABANDON 작업을 실행하여 결함있는 인스턴스를 종료하고 자동 조정 그룹에서 다른 인스턴스를 시작합니다..

상태 확인을 통과하지 못한 것 외에도 사용자 데이터 스크립트가 다른 시점에서 실패 할 수 있습니다 (예 : 일시적인 연결 문제로 인해 소프트웨어 설치가 불가능한 경우).

우리는 새로운 인스턴스가 결코 건강 해지지 않을 것이라는 것을 깨닫 자마자 실패하기를 원합니다. 이를 위해 사용자 데이터 스크립트에서 ERR 트랩을 set -o errtrace와 함께 설정하여 ABANDON 라이프 사이클 조치를 전송하는 함수를 호출하여 결함있는 인스턴스가 가능한 빨리 종료 될 수 있도록합니다..

사용자 데이터 스크립트

사용자 데이터 스크립트는 인스턴스에 필요한 모든 소프트웨어를 설치합니다. Ansible을 사용하여 인스턴스 및 Capistrano를 프로비저닝하여 오랫동안 애플리케이션을 배포 했으므로 여기에서도 사용하므로 정기적 인 배치와 재 구축 간의 차이를 최소화 할 수 있습니다..

사용자 데이터 스크립트는 Ansible 프로비저닝 스크립트가 포함 된 Github에서 애플리케이션 저장소를 확인한 다음 Ansible을 실행하고 로컬 호스트를 가리키는 Capistrano를 실행합니다..

코드를 체크 아웃 할 때 현재 배포 된 버전의 응용 프로그램이 재 구축 중에 배포되어 있는지 확인해야합니다. Capistrano 배포 스크립트에는 현재 배포 된 커밋 SHA를 저장하는 S3의 파일을 업데이트하는 작업이 포함되어 있습니다. 재 구축이 발생하면 시스템은 해당 파일에서 배치 될 커밋을 선택합니다..

소프트웨어 업데이트는 unattended-upgrade -d 명령을 사용하여 포 그라운드에서 무인 업그레이드를 실행하여 적용됩니다. 완료되면 인스턴스가 재부팅되고 상태 확인이 시작됩니다..

비밀 다루기

서버는 EC2 매개 변수 저장소에서 가져온 비밀 (예 : Ansible Vault 암호)에 임시로 액세스해야합니다. 서버는 재 구축 중 짧은 기간 동안 만 비밀에 액세스 할 수 있습니다. 가져온 후에는 초기 인스턴스 프로파일을 즉시 애플리케이션을 실행하는 데 필요한 리소스에만 액세스 할 수있는 다른 프로파일로 바꿉니다..

인스턴스의 영구 메모리에 비밀을 저장하지 않기를 원합니다. 우리가 디스크에 저장하는 유일한 비밀은 암호문이 아니라 Github SSH 키입니다. 우리는 Ansible Vault 암호도 저장하지 않습니다.

그러나 이러한 암호를 각각 SSH와 Ansible에 전달해야하며, 대화 형 모드에서만 가능합니다 (즉, 유틸리티는 사용자가 수동으로 암호를 입력하라는 프롬프트를 표시합니다). 암호가 명령의 일부인 경우 쉘 히스토리에 저장되며 ps를 실행하면 시스템의 모든 사용자가 볼 수 있습니다. 우리는 expect 유틸리티를 사용하여 해당 도구와의 상호 작용을 자동화합니다.

배고 있다 << EOF
cd $ {repo_dir}
spawn make ansible_local env = $ {deploy_env} stack = $ {stack} hostname = $ {server_hostname}
시간 초과 설정 2
'볼트 비밀번호'가 필요합니다
보내다 "$ {vault_password} \ r"
시간 초과 설정 900
{
"도달 불가능 = 0 실패 = 0" {
출구 0
}
eof {
1 번 출구
}
타임 아웃 {
1 번 출구
}
}
EOF

재 구축 트리거

인프라를 생성 / 업데이트하는 데 사용 된 것과 동일한 Cloudformation 스크립트를 실행하여 재 구축을 트리거하므로, 재 구축 중에 업데이트되지 않아야 할 인프라의 일부를 실수로 업데이트하지 않아야합니다..

Cloudformation 스택에 제한적인 스택 정책을 설정하여 재 구축에 필요한 리소스 만 업데이트함으로써이를 달성합니다.

{
"성명서" : [
{
"효과" : "허용하다",
"동작" : "업데이트 : 수정",
"주요한": "*",
"자원" : [
"LogicalResourceId / * AutoScalingGroup"
] },
{
"효과" : "허용하다",
"동작" : "업데이트 : 교체",
"주요한": "*",
"자원" : [
"LogicalResourceId / * LaunchConfiguration"
] }
] }

실제 인프라 업데이트를 수행해야하는 경우 해당 리소스에 대한 업데이트를 명시 적으로 허용하도록 스택 정책을 수동으로 업데이트해야합니다..

서버 호스트 이름과 IP가 매일 바뀌기 때문에 로컬 Ansible 인벤토리와 SSH 구성을 업데이트하는 스크립트가 있습니다. 태그별로 AWS API를 통해 인스턴스를 감지하고 ERB 템플릿에서 인벤토리 및 구성 파일을 렌더링하며 SSH known_hosts에 새 IP를 추가합니다..

ExpressVPN은 최고의 보안 표준을 따릅니다.

서버 재 구축은 특정 위협으로부터 우리를 보호합니다. 공격자는 커널 / 소프트웨어 취약점을 통해 서버에 액세스합니다..

그러나 이는 정기적 인 보안 감사를 받고 인터넷에서 중요한 시스템에 액세스 할 수 없도록하는 등 인프라를 안전하게 유지하는 많은 방법 중 하나입니다..

또한 모든 코드 및 내부 프로세스가 최고의 보안 표준을 준수하는지 확인합니다.

ExpressVPN이 웹 서버를 패치하고 안전하게 유지하는 방법
admin Author
Sorry! The Author has not filled his profile.