Outbound VPC Proxy

 

Outbound VPC Proxy

   

AWS Outbound Proxy with Domain WhiteListing

13-12-2021

Pawan Rai

 
Why Filter Traffic?

when it comes to getting hacked, it’s not a matter of if but when. And to protect against that scenario, encrypting data at rest is a must. But, invariably one or more data sources is left unencrypted and that leaves an opening for your data to be compromised.

How to Filter Traffic?

In AWS We have a Limited ways to Manage Traffic and Filter unwanted URL access

We will discuss 3 methods for controlling outbound internet access in AWS VPCs:

  1. AWS Native Services – AWS NAT Gateway & AWS NAT Instances
  2. Proxies, such as Squid Proxy
  3. Third-party In-Line VPC NAT Gateways, such as Aviatrix Gateway
AWS Native Services

AWS provides NAT Instances and NAT Gateways to allow your private subnet instances to connect to the internet. It is recommended that you use the fully managed, highly available NAT gateway service instead of NAT instances.

When filtering outbound traffic using these native services you will need to rely on security groups and Network ACLs. One benefit to the NAT instance is that security groups can be associated directly with NAT instances but cannot be associated with the NAT gateway. If you use the NAT gateway and you would like to control outbound traffic using security groups, you must associate the EC2 instances behind the gateway with the security group.

Web Proxy(We are using this in our organization)

A web proxy is a standard approach that many administrators use to filter traffic.

With this technique, all traffic is routed through one or more NAT instances with a proxy engine like Squid installed. While you can route traffic to a proxy via modifications on the Operating System, we will only consider a central proxy managed through AWS route table here.

Steps: (Currently Testing)

  1. First We have to Create VPC That is able to Connect to the internet.
  2. We Template is able to Create the Proxy Server But which Servers is Going To use this Proxy Server is Need to be Config.

Config server on Which you want to use Proxy

  1. export http_proxy=http://<Proxy-DOMAIN>:<Proxy-Port>
  2. export https_proxy=$http_proxy
  3. Replace <Proxy-DOMAIN> with the domain of the load balancer, which you can find in the stack output parameter.
  4. Replace <Proxy-Port> with the port of your proxy, which is also listed in the stack output parameter.

Which I used for Config

  1. export http_proxy=http://OutboundProxyLoadBalancer-93f04e0f88bb450e.elb.us-east-1.amazonaws.com:3128 && export https_proxy=$http_proxy
How Resources are Connect with Each Other?

Figure 1: Solution overview

We can change the Allowed URL with Secret Manager

Template For the Outbound Proxy Server Creation

  1. Description: Outbound filtering proxy
  2.  
  3. Parameters:
  4.  
  5. WhitelistedDomains:
  6. Type: String
  7. Default: .amazonaws.com, .debian.org, twitter.com
  8. Description: Whitelisted domains comma separated
  9.  
  10. CustomDNS:
  11. Type: String
  12. Default: default
  13. Description: Provide optional a DNS server for domain filtering, like OpenDNS (comma separated, like 8.8.8.8,8.8.8.7)
  14.  
  15. KeyName:
  16. Type: “String”
  17. Description: Name of RSA key for EC2 access for testing only.
  18. Default: ‘luxmiVirginia’
  19.  
  20. ProxyPort:
  21. Type: String
  22. Default: 3128
  23. Description: Port Proxy
  24.  
  25.  
  26. VpcId:
  27. Description: VPC ID Where the Proxy will be installed
  28. Type: “AWS::EC2::VPC::Id”
  29.  
  30. PrivateSubnetIDs:
  31. Description: Private SubnetIDs where the Network LoadBalancer will be placed (Select min 2 max 3)
  32. Type: “List<AWS::EC2::Subnet::Id>”
  33.  
  34. PublicSubnetIDs:
  35. Description: Public SubnetIDs where the proxy will be placed (Select min 2 max 3)
  36. Type: “List<AWS::EC2::Subnet::Id>”
  37.  
  38. InstanceType:
  39. Description: WebServer EC2 instance type
  40. Type: String
  41. Default: t2.micro
  42. AllowedValues:
  43. – t2.micro
  44. – t3.nano
  45. – t3.micro
  46. – t3.small
  47. – t3.medium
  48. – t3.large
  49. – m3.medium
  50. – m3.large
  51. – m3.xlarge
  52. – m3.2xlarge
  53. – m4.large
  54. – m4.xlarge
  55. – m4.2xlarge
  56. – m5.large
  57. – m5.xlarge
  58. – m5.2xlarge
  59. – c3.large
  60. – c3.xlarge
  61. – c4.large
  62. ConstraintDescription: must be a valid EC2 instance type.
  63.  
  64. NetworkAllowedCIDR:
  65. Description: CIDR allowed in Proxy Security Group. The allowed block size is between a /32 netmask and /8 netmask
  66. Type: String
  67. Default: 172.31.0.0/16
  68. AllowedPattern: ^[.0-9]*\/([89]|[12][0-9]|3[0-2])$
  69.  
  70. LatestAmiId:
  71. Type: ‘AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>’
  72. Default: ‘/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2’
  73. Description: AMI ID pointer in SSM. Default latest AMI Amazon Linux2.
  74.  
  75. Metadata:
  76. ‘AWS::CloudFormation::Interface’:
  77. ParameterGroups:
  78. – Label:
  79. default: Proxy parameter
  80. Parameters:
  81. – WhitelistedDomains
  82. – CustomDNS
  83. – ProxyPort
  84. – InstanceType
  85. – LatestAmiId
  86. – KeyName
  87.  
  88. – Label:
  89. default: Network parameter
  90. Parameters:
  91. – VpcId
  92. – PrivateSubnetIDs
  93. – PublicSubnetIDs
  94. – NetworkAllowedCIDR
  95.  
  96. ParameterLabels:
  97. WhitelistedDomains:
  98. default: Allowed domains (whitelisted)
  99. CustomDNS:
  100. default: Custom DNS servers
  101. ProxyPort:
  102. default: Proxy Port
  103. InstanceType:
  104. default: Instance Type
  105. LatestAmiId:
  106. default: AMI ID
  107. KeyName:
  108. default: SSH Key name
  109. VpcId:
  110. default: VPC ID
  111. PrivateSubnetIDs:
  112. default: Private Subnet IDs
  113. PublicSubnetIDs:
  114. default: Public Subnet IDs
  115. NetworkAllowedCIDR:
  116. default: Allowed client CIRD
  117.  
  118.  
  119. Conditions:
  120.  
  121. AddSSHKey: !Not
  122. – !Equals
  123. – ”
  124. – !Ref KeyName
  125.  
  126. Resources:
  127.  
  128. OutboundProxyRole:
  129. Type: AWS::IAM::Role
  130. Properties:
  131. RoleName: !Sub “Outbound-proxy-${AWS::StackName}”
  132. AssumeRolePolicyDocument:
  133. Version: ‘2012-10-17’
  134. Statement:
  135. – Effect: Allow
  136. Principal:
  137. Service:
  138. – ec2.amazonaws.com
  139. Action:
  140. – sts:AssumeRole
  141. Path: “/”
  142. Policies:
  143. – PolicyName: LogRolePolicy
  144. PolicyDocument:
  145. Version: ‘2012-10-17’
  146. Statement:
  147. – Effect: Allow
  148. Action:
  149. – logs:CreateLogGroup
  150. – logs:CreateLogStream
  151. – logs:PutLogEvents
  152. – logs:DescribeLogStreams
  153. Resource:
  154. – !GetAtt OutboundProxyLogGroup.Arn
  155. – PolicyName: AssociateEIP
  156. PolicyDocument:
  157. Version: ‘2012-10-17’
  158. Statement:
  159. – Effect: Allow
  160. Action:
  161. – ec2:AssociateAddress
  162. – ec2:Describe*
  163. Resource:
  164. – “*”
  165. – PolicyName: RevokeAuthorizeSG
  166. PolicyDocument:
  167. Version: ‘2012-10-17’
  168. Statement:
  169. – Effect: Allow
  170. Action:
  171. – ec2:RevokeSecurityGroupIngress
  172. – ec2:AuthorizeSecurityGroupIngress
  173. – ec2:Describe*
  174. Resource:
  175. – “*”
  176. – PolicyName: GetSecret
  177. PolicyDocument:
  178. Version: ‘2012-10-17’
  179. Statement:
  180. – Effect: Allow
  181. Action:
  182. – secretsmanager:GetSecretValue
  183. Resource:
  184. – !Ref WhitelistedSitesSecret
  185. – PolicyName: CloudWatchMetric
  186. PolicyDocument:
  187. Version: ‘2012-10-17’
  188. Statement:
  189. – Effect: Allow
  190. Action:
  191. – cloudwatch:PutMetricData
  192. Resource:
  193. – “*”
  194.  
  195. WhitelistedSitesSecret:
  196. Type: ‘AWS::SecretsManager::Secret’
  197. Properties:
  198. Name: Proxy-Domains-Whitelisting
  199. Description: This secret contains the proxy whitelisted domains
  200. SecretString: !Ref WhitelistedDomains
  201.  
  202. FixedEIPa:
  203. Type: AWS::EC2::EIP
  204. Properties:
  205. Domain: vpc
  206.  
  207. FixedEIPb:
  208. Type: AWS::EC2::EIP
  209. Properties:
  210. Domain: vpc
  211.  
  212. FixedEIPc:
  213. Type: AWS::EC2::EIP
  214. Properties:
  215. Domain: vpc
  216.  
  217. FixedEIPd:
  218. Type: AWS::EC2::EIP
  219. Properties:
  220. Domain: vpc
  221.  
  222. LoadBalancer:
  223. Type: AWS::ElasticLoadBalancingV2::LoadBalancer
  224. Properties:
  225. Scheme: internal
  226. Type: network
  227. Name: OutboundProxyLoadBalancer
  228. Subnets: !Ref PrivateSubnetIDs
  229.  
  230. NetworkLoadBalancerTargetGroup:
  231. Type: AWS::ElasticLoadBalancingV2::TargetGroup
  232. Properties:
  233. Name: OutboundProxyTargetGroup
  234. Port: !Ref ProxyPort
  235. Protocol: TCP
  236. VpcId: !Ref VpcId
  237. TargetGroupAttributes:
  238. – Key: deregistration_delay.timeout_seconds
  239. Value: 60
  240. Tags:
  241. – Key: Name
  242. Value: SMARTProxyTargetGroup
  243. LoadBalancerListenerHTTPS:
  244. Type: AWS::ElasticLoadBalancingV2::Listener
  245. Properties:
  246. DefaultActions:
  247. – Type: forward
  248. TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup
  249. LoadBalancerArn: !Ref LoadBalancer
  250. Port: !Ref ProxyPort
  251. Protocol: TCP
  252.  
  253. OutboundProxyProfile:
  254. Type: AWS::IAM::InstanceProfile
  255. Properties:
  256. Path: “/”
  257. InstanceProfileName: !Sub “Proxy-EC2-${AWS::StackName}”
  258. Roles:
  259. – !Ref OutboundProxyRole
  260.  
  261. OutboundProxySecurityGroup:
  262. Type: AWS::EC2::SecurityGroup
  263. Properties:
  264. GroupDescription: Allow access to Outbound Proxy
  265. VpcId: !Ref VpcId
  266. SecurityGroupIngress:
  267. – CidrIp: !Ref NetworkAllowedCIDR
  268. FromPort: !Ref ProxyPort
  269. ToPort: !Ref ProxyPort
  270. IpProtocol: tcp
  271.  
  272. OutboundProxyASG:
  273. Type: AWS::AutoScaling::AutoScalingGroup
  274. Properties:
  275. VPCZoneIdentifier: !Ref PublicSubnetIDs
  276. Cooldown: 120
  277. LaunchConfigurationName: !Ref OutboundProxyLaunchConfig
  278. MaxSize: 3
  279. MinSize: 1
  280. TargetGroupARNs:
  281. – Ref: “NetworkLoadBalancerTargetGroup”
  282. TerminationPolicies:
  283. – OldestInstance
  284. Tags:
  285. – Key: Name
  286. PropagateAtLaunch: ‘true’
  287. Value: outbound-proxy
  288. – Key: AppVersion
  289. PropagateAtLaunch: ‘true’
  290. Value: 1.0.0
  291. – Key: ApplicationID
  292. PropagateAtLaunch: ‘true’
  293. Value: outbound-proxy
  294. CreationPolicy:
  295. ResourceSignal:
  296. Timeout: PT15M
  297. Count: ‘1’
  298. UpdatePolicy:
  299. AutoScalingScheduledAction:
  300. IgnoreUnmodifiedGroupSizeProperties: true
  301. AutoScalingRollingUpdate:
  302. MinInstancesInService: 1
  303. MaxBatchSize: 1
  304. PauseTime: PT15M
  305. WaitOnResourceSignals: ‘true’
  306. SuspendProcesses:
  307. – ScheduledActions
  308.  
  309. ScaleOutPolicy:
  310. Type: AWS::AutoScaling::ScalingPolicy
  311. Properties:
  312. AdjustmentType: ChangeInCapacity
  313. AutoScalingGroupName:
  314. Ref: OutboundProxyASG
  315. Cooldown: ’90’
  316. ScalingAdjustment: ‘1’
  317.  
  318. CPUAlarmHigh:
  319. Type: AWS::CloudWatch::Alarm
  320. Properties:
  321. EvaluationPeriods: ‘1’
  322. Statistic: Average
  323. Threshold: ’80’
  324. AlarmDescription: Alarm if CPU too high (50%) or metric disappears indicating instance
  325. is down
  326. Period: ’60’
  327. AlarmActions:
  328. – Ref: ScaleOutPolicy
  329. Namespace: AWS/EC2
  330. Dimensions:
  331. – Name: AutoScalingGroupName
  332. Value:
  333. Ref: OutboundProxyASG
  334. ComparisonOperator: GreaterThanThreshold
  335. MetricName: CPUUtilization
  336.  
  337. ScaleInPolicy:
  338. Type: AWS::AutoScaling::ScalingPolicy
  339. Properties:
  340. AdjustmentType: ChangeInCapacity
  341. AutoScalingGroupName:
  342. Ref: OutboundProxyASG
  343. Cooldown: ’90’
  344. ScalingAdjustment: ‘-1’
  345.  
  346. CPUAlarmLow:
  347. Type: AWS::CloudWatch::Alarm
  348. Properties:
  349. EvaluationPeriods: ‘1’
  350. Statistic: Average
  351. Threshold: ’10’
  352. AlarmDescription: Alarm if CPU low (10%) or metric disappears indicating instance
  353. is down
  354. Period: ’60’
  355. AlarmActions:
  356. – Ref: ScaleInPolicy
  357. Namespace: AWS/EC2
  358. Dimensions:
  359. – Name: AutoScalingGroupName
  360. Value:
  361. Ref: OutboundProxyASG
  362. ComparisonOperator: LessThanThreshold
  363. MetricName: CPUUtilization
  364.  
  365. OutboundProxyLaunchConfig:
  366. Type: AWS::AutoScaling::LaunchConfiguration
  367. Metadata:
  368. Comment: Configures Outbound Proxy
  369. AWS::CloudFormation::Init:
  370. config:
  371. files:
  372. “/root/update-dns.sh”:
  373. content: !Sub |
  374. # DNS List comma delimited
  375. dns_list=”${CustomDNS}”
  376. #
  377. # check if default
  378. if [[ $dns_list == “default” ]]; then
  379. exit
  380. fi
  381. #
  382. # split to list
  383. array=(${!dns_list//,/ })
  384. int_list=`ls /etc/sysconfig/network-scripts/ifcfg-* | grep -v “\-lo$\|old$”`
  385.  
  386. # for all interfaces except lookback
  387. for int in ${!int_list[@]}
  388. do
  389. # remove spaces
  390. $int=${!int//[[:blank:]]/}
  391. echo “working on $int”
  392. # make tmp file without DNS settings
  393. grep -ve “PEERDNS=\|DNS.=” $int > ./tmp.int.conf
  394. grep -v “nameserver” /etc/resolv.conf > ./tmp.resolv.conf
  395. echo “PEERDNS=yes” >> ./tmp.int.conf
  396. counter=1
  397. for i in ${!array[@]}
  398. do
  399. echo “DNS${!counter}=${!i}” >> ./tmp.int.conf
  400. echo “nameserver ${!i}” >> ./tmp.resolv.conf
  401. ((counter++))
  402. done
  403. # update the interface config
  404. mv $int ${!int}.old
  405. cp ./tmp.int.conf $int
  406. done
  407. # update the resolv.conf
  408. mv /etc/resolv.conf /etc/resolv.conf.old
  409. cp ./tmp.resolv.conf /etc/resolv.conf
  410. # clear squid cache if squid is running. Relevant for dns content filtering
  411. # systemctl status squid && systemctl stop squid && rm -rf /var/spool/squid/ && squid -z && systemctl start squid
  412. echo “done”
  413. mode: ‘000755’
  414. owner: “root”
  415. group: “root”
  416. “/etc/awslogs/awscli.conf”:
  417. content: !Sub |
  418. [plugins]
  419. cwlogs = cwlogs
  420. [default]
  421. region = ${AWS::Region}
  422. mode: ‘000755’
  423. owner: “root”
  424. group: “root”
  425. “/root/fetch-config-cron.sh”:
  426. content: !Sub |
  427. aws secretsmanager get-secret-value –secret-id ${WhitelistedSitesSecret} –region ${AWS::Region} > ~/.tmp.hosts
  428. upstreamVersion=$(grep VersionId ~/.tmp.hosts)
  429. hostVersion=$(cat ~/configVersion) || hostVersion=”0″
  430. # update if config
  431. if [[ $upstreamVersion != $hostVersion ]]; then
  432. mv /etc/squid/squid.allowed.sites.txt /etc/squid/squid.allowed.sites.txt.old
  433. grep SecretString ~/.tmp.hosts | sed ‘s/^.*SecretString\”: \”\(.*\)\”\,/\1/’ | tr -d ” ” | tr “,” “\n” > /etc/squid/squid.allowed.sites.txt
  434. grep VersionId ~/.tmp.hosts > ~/configVersion
  435. systemctl restart squid
  436. echo “Squid config updated”
  437. logger “Squid config updated by cron-job from AWS secret store ${WhitelistedSitesSecret}”
  438. fi
  439. mode: ‘000755’
  440. owner: “root”
  441. group: “root”
  442. “/root/get-stats-cron.sh”:
  443. content: !Sub |
  444. #!/bin/bash
  445. #
  446. # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  447. # SPDX-License-Identifier: MIT-0#
  448. #
  449. # gets statistics from squid proxy and pushes them to CloudWatch
  450. #
  451. ###
  452. region=`curl –silent http://169.254.169.254/latest/dynamic/instance-identity/document | grep region | cut -f 4 -d ‘”‘`
  453. instanceId=`curl –silent http://169.254.169.254/latest/meta-data/instance-id`
  454.  
  455. squidclient -h localhost cache_object://localhost/ mgr:5min | grep “client_http.request\|client_http.hits\|client_http.errors\|client_http.kbytes_in\|client_http.kbytes_out\|server.all.” | while read line ; do
  456. name=`echo $line | cut -d “=” -f 1`
  457. value=`echo $line | cut -d “=” -f 2 | sed “s/[^0-9\.]*//g” `
  458. aws cloudwatch put-metric-data –metric-name “$name” –namespace Proxy –dimensions InstanceID=”$instanceId” –value “$value” –region $region
  459. done
  460. mode: ‘000755’
  461. owner: “root”
  462. group: “root”
  463. “/etc/squid/squid.allowed.sites.txt”:
  464. content: |
  465. .amazon.com
  466. mode: ‘000400’
  467. owner: “root”
  468. group: “root”
  469. “/etc/squid/squid.conf”:
  470. content: !Sub |
  471. # Recommended minimum configuration:
  472. #
  473. # Example rule allowing access from your local networks.
  474. # Adapt to list your (internal) IP networks from where browsing
  475. # should be allowed
  476. acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
  477. acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
  478. acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
  479. acl localnet src fc00::/7 # RFC 4193 local private network range
  480. acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
  481. acl localnet src 127.0.0.1
  482. # The Instance Metadata Service
  483. # (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instance-metadata-limiting-access)
  484. acl imds dst 169.254.169.254
  485. acl SSL_ports port 443
  486. acl Safe_ports port 80 # http
  487. acl Safe_ports port 21 # ftp
  488. acl Safe_ports port 443 # https
  489. acl Safe_ports port 70 # gopher
  490. acl Safe_ports port 210 # wais
  491. acl Safe_ports port 1025-65535 # unregistered ports
  492. acl Safe_ports port 280 # http-mgmt
  493. acl Safe_ports port 488 # gss-http
  494. acl Safe_ports port 591 # filemaker
  495. acl Safe_ports port 777 # multiling http
  496. acl CONNECT method CONNECT
  497. #
  498. # Recommended minimum Access Permission configuration:
  499. #
  500. # Deny requests to the Instance Metadata Service
  501. http_access deny imds
  502. # Deny requests to certain unsafe ports
  503. http_access deny !Safe_ports
  504. # Deny CONNECT to other than secure SSL ports
  505. http_access deny CONNECT !SSL_ports
  506. # Only allow cachemgr access from localhost
  507. http_access allow localhost manager
  508. http_access deny manager
  509. # Deny requests to services running on localhost
  510. http_access deny to_localhost
  511. #
  512. # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
  513. #
  514. # Example rule allowing access from your local networks.
  515. # Adapt localnet in the ACL section to list your (internal) IP networks
  516. # from where browsing should be allowed
  517. acl allowed_http_sites dstdomain “/etc/squid/squid.allowed.sites.txt”
  518. http_access allow allowed_http_sites
  519. #http_access allow localnet
  520. #http_access allow localhost
  521. # And finally deny all other access to this proxy
  522. http_access deny all
  523. # Squid normally listens to port 3128, but needs to be parametrized here
  524. http_port 0.0.0.0:${ProxyPort} ssl-bump cert=/etc/squid/cert.pem
  525. acl allowed_https_sites ssl::server_name “/etc/squid/squid.allowed.sites.txt”
  526. acl step1 at_step SslBump1
  527. acl step2 at_step SslBump2
  528. acl step3 at_step SslBump3
  529. ssl_bump peek step1 all
  530. ssl_bump peek step2 allowed_https_sites
  531. ssl_bump splice step3 allowed_https_sites
  532. ssl_bump terminate step2 all
  533. # Uncomment and adjust the following to add a disk cache directory.
  534. #cache_dir ufs /var/spool/squid 100 16 256
  535. # Leave coredumps in the first cache dir
  536. coredump_dir /var/spool/squid
  537. #
  538. # Add any of your own refresh_pattern entries above these.
  539. #
  540. refresh_pattern ^ftp: 1440 20% 10080
  541. refresh_pattern ^gopher: 1440 0% 1440
  542. refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
  543. refresh_pattern . 0 20% 4320
  544. “/etc/awslogs/awslogs.conf”:
  545. content: !Sub |
  546. [general]
  547. state_file = /var/lib/awslogs/agent-state
  548. [/var/log/squid/access.log]
  549. file = /var/log/squid/access.log
  550. log_group_name = ${OutboundProxyLogGroup}
  551. log_stream_name = {instance_id}/squid_access.log
  552. #datetime_format = %d/%b/%Y:%H:%M:%S
  553. mode: ‘000400’
  554. owner: “root”
  555. group: “root”
  556. “/etc/cfn/cfn-hup.conf”:
  557. content: !Sub |
  558. [main]
  559. stack= ${AWS::StackId}
  560. region=${AWS::Region}
  561. interval=5
  562. mode: “000400”
  563. owner: “root”
  564. group: “root”
  565. “/etc/cfn/hooks.d/cfn-auto-reloader.conf”:
  566. content: !Sub |
  567. [cfn-auto-reloader-hook]
  568. triggers=post.update
  569. path=Resources.OutboundProxyLaunchConfig.Metadata.AWS::CloudFormation::Init
  570. action=/opt/aws/bin/cfn-init -v –stack ${AWS::StackName} –resource OutboundProxyLaunchConfig –region ${AWS::Region}
  571. runas=root
  572. mode: “000400”
  573. owner: “root”
  574. group: “root”
  575. Properties:
  576. AssociatePublicIpAddress: True
  577. ImageId: !Ref LatestAmiId
  578. InstanceType: !Ref InstanceType
  579. KeyName: !If
  580. – AddSSHKey
  581. – !Ref KeyName
  582. – !Ref “AWS::NoValue”
  583. SecurityGroups:
  584. – !Ref OutboundProxySecurityGroup
  585.  
  586. IamInstanceProfile:
  587. Ref: OutboundProxyProfile
  588. UserData:
  589. Fn::Base64: !Sub |
  590. #!/bin/bash -xe
  591. yum -y install python-pip
  592. yum -y install python-setuptools
  593. yum install -y awscli
  594. # install squid
  595. yum install -y squid
  596. # install the CloudWatch Logs agent
  597. yum install -y awslogs
  598. # Get the latest CloudFormation package
  599. easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
  600. # Start cfn-init
  601. /opt/aws/bin/cfn-init -s ${AWS::StackId} -r OutboundProxyLaunchConfig –region ${AWS::Region} || error_exit ‘Failed to run cfn-init’
  602. # Start up the cfn-hup daemon to listen for changes to the launch configuration metadata
  603. /opt/aws/bin/cfn-hup || error_exit ‘Failed to start cfn-hup’
  604. # start the cloud watch agent
  605. systemctl start awslogsd
  606. # get the IP allocation id
  607. EIPs=(${FixedEIPa.AllocationId} ${FixedEIPb.AllocationId} ${FixedEIPc.AllocationId} ${FixedEIPd.AllocationId})
  608. for i in ${!EIPs[@]}; do
  609. out=$(aws ec2 describe-addresses –region ${AWS::Region} –allocation-ids $i)
  610. if [[ $out != *AssociationId* ]]; then
  611. freeEIP=$i
  612. break
  613. fi
  614. done
  615. # bind the address
  616. echo “binding EIP”
  617. aws ec2 associate-address –region ${AWS::Region} –instance-id $(curl -s http://169.254.169.254/latest/meta-data/instance-id) –allocation-id $freeEIP –allow-reassociation || error_exit ‘Failed to Associate Elastic IP’
  618. # generate dummy certificate
  619. openssl req -x509 -newkey rsa:4096 -keyout /etc/squid/cert.pem -out /etc/squid/cert.pem -days 3650 -subj “/C=XX/ST=XX/L=squid/O=squid/CN=squid” -nodes
  620. # get the whitelisted domain
  621. /root/fetch-config-cron.sh
  622. # start squit
  623. systemctl start squid
  624. # cron to update whitelist if needed every 5 min
  625. echo “*/5 * * * * /root/fetch-config-cron.sh” | crontab –
  626. # cron to to get and push proxy stats
  627. (crontab -l ; echo “*/5 * * * * /root/get-stats-cron.sh”) | crontab –
  628. # set up DNS if needed
  629. if [[ ${CustomDNS} != “default” ]]; then
  630. /root/update-dns.sh
  631. fi
  632. # All done so signal success
  633. /opt/aws/bin/cfn-signal -e $? –stack ${AWS::StackId} –resource OutboundProxyASG –region ${AWS::Region}
  634. echo “User data done”
  635.  
  636. OutboundProxyLogGroup:
  637. Type: AWS::Logs::LogGroup
  638. Properties:
  639. RetentionInDays: 30
  640. LogGroupName: !Sub “Proxy-${AWS::StackName}”
  641.  
  642. Outputs:
  643. CloudWatchLogGroupName:
  644. Description: The name of the CloudWatch log group for outbound proxy
  645. Value: !Ref OutboundProxyLogGroup
  646. Export:
  647. Name: Proxy-CloudWatchLogGroupName
  648.  
  649. OutboundProxyDomain:
  650. Description: Proxy DNS name to be used in the clients
  651. Value: !GetAtt LoadBalancer.DNSName
  652. Export:
  653. Name: Proxy-Domain
  654.  
  655. OutboundProxyPort:
  656. Description: Port of the Proxy
  657. Value: !Ref ProxyPort
  658. Export:
  659. Name: Proxy-Port
  660.  
  661. EgressIP1:
  662. Description: Outbound Proxy source IP (first)
  663. Value: !Ref FixedEIPa
  664. Export:
  665. Name: Proxy-Egress-IP-1
  666. EgressIP2:
  667. Description: Outbound Proxy source IP (second)
  668. Value: !Ref FixedEIPb
  669. Export:
  670. Name: Proxy-Egress-IP-2
  671. EgressIP3:
  672. Description: Outbound Proxy source IP (third)
  673. Value: !Ref FixedEIPc
  674. Export:
  675. Name: Proxy-Egress-IP-3
  676. EgressIP4:
  677. Description: Outbound Proxy source IP (fourth)
  678. Value: !Ref FixedEIPd
  679. Export:
  680. Name: Proxy-Egress-IP-4
  681.  
  682. SecurityGroupProxy:
  683. Description: Proxy security group
  684. Value: SecurityGroup_Proxy
  685. Export:
  686. Name: Proxy-SecurityGroup
  687.  
  688. LinuxProxySettings:
  689. Description: Linux proxy settings. Copy and paste to your shell to set the proxy
  690. Value: !Sub “export http_proxy=http://${LoadBalancer.DNSName}:${ProxyPort} && export https_proxy=$http_proxy”
  691. Export:
  692. Name: LinuxProxySettings
VPC Template Which Work With outbound Proxy
  1. AWSTemplateFormatVersion: ‘2010-09-09’
  2. Description: Create VPC for proxy demo
  3. Parameters:
  4.  
  5. VPCCidrBlock:
  6. Type: String
  7. Description: CIDR block for VPC to deploy. (X.X.X.X/X)
  8. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  9. Default: 10.0.0.0/16
  10. PublicSubnetCIDR1:
  11. Type: String
  12. Description: First public subnet CIDR
  13. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  14. Default: 10.0.0.0/24
  15. PublicSubnetCIDR2:
  16. Type: String
  17. Description: Second public subnet CIDR
  18. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  19. Default: 10.0.1.0/24
  20. PublicSubnetCIDR3:
  21. Type: String
  22. Description: Third public subnet CIDR
  23. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  24. Default: 10.0.2.0/24
  25. PrivateSubnetCIDR1:
  26. Type: String
  27. Description: First private subnet CIDR
  28. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  29. Default: 10.0.3.0/24
  30. PrivateSubnetCIDR2:
  31. Type: String
  32. Description: Second private subnet CIDR
  33. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  34. Default: 10.0.4.0/24
  35. PrivateSubnetCIDR3:
  36. Type: String
  37. Description: Thirs private subnet CIDR
  38. AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
  39. Default: 10.0.5.0/24
  40. Resources:
  41. VPC:
  42. Type: AWS::EC2::VPC
  43. Properties:
  44. CidrBlock: !Ref ‘VPCCidrBlock’
  45. EnableDnsSupport: ‘true’
  46. EnableDnsHostnames: ‘true’
  47. InstanceTenancy: default
  48. Tags:
  49. – Key: Name
  50. Value: !Sub vpc-${AWS::StackName}
  51.  
  52. InternetGateway:
  53. Type: AWS::EC2::InternetGateway
  54. Properties:
  55. Tags:
  56. – Key: Name
  57. Value: Internet Gateway
  58. InternetGatewayAttachment:
  59. Type: AWS::EC2::VPCGatewayAttachment
  60. Properties:
  61. InternetGatewayId: !Ref ‘InternetGateway’
  62. VpcId: !Ref ‘VPC’
  63. PublicSubnet1:
  64. Type: AWS::EC2::Subnet
  65. Properties:
  66. CidrBlock: !Ref ‘PublicSubnetCIDR1’
  67. AvailabilityZone: !Select
  68. – ‘0’
  69. – !GetAZs ”
  70. MapPublicIpOnLaunch: ‘false’
  71. Tags:
  72. – Key: Name
  73. Value: Public subnet 1
  74.  
  75. VpcId: !Ref ‘VPC’
  76. PublicSubnet2:
  77. Type: AWS::EC2::Subnet
  78. Properties:
  79. CidrBlock: !Ref ‘PublicSubnetCIDR2’
  80. AvailabilityZone: !Select
  81. – ‘1’
  82. – !GetAZs ”
  83. MapPublicIpOnLaunch: ‘false’
  84. Tags:
  85. – Key: Name
  86. Value: Public subnet 2
  87. VpcId: !Ref ‘VPC’
  88. PublicSubnet3:
  89. Type: AWS::EC2::Subnet
  90. Properties:
  91. CidrBlock: !Ref ‘PublicSubnetCIDR3’
  92. AvailabilityZone: !Select
  93. – ‘2’
  94. – !GetAZs ”
  95. MapPublicIpOnLaunch: ‘false’
  96. Tags:
  97. – Key: Name
  98. Value: Pubic subnet 3
  99.  
  100. VpcId: !Ref ‘VPC’
  101. PublicRouteTable:
  102. Type: AWS::EC2::RouteTable
  103. Properties:
  104. VpcId: !Ref ‘VPC’
  105. Tags:
  106. – Key: Name
  107. Value: Public Route Table
  108. AttachPublicSubnet1RouteTable:
  109. Type: AWS::EC2::SubnetRouteTableAssociation
  110. Properties:
  111. RouteTableId: !Ref ‘PublicRouteTable’
  112. SubnetId: !Ref ‘PublicSubnet1’
  113. AttachPublicSubnet2RouteTable:
  114. Type: AWS::EC2::SubnetRouteTableAssociation
  115. Properties:
  116. RouteTableId: !Ref ‘PublicRouteTable’
  117. SubnetId: !Ref ‘PublicSubnet2’
  118. AttachPublicSubnet3RouteTable:
  119. Type: AWS::EC2::SubnetRouteTableAssociation
  120. Properties:
  121. RouteTableId: !Ref ‘PublicRouteTable’
  122. SubnetId: !Ref ‘PublicSubnet3’
  123. PublicRoutetoInternet:
  124. Type: AWS::EC2::Route
  125. Properties:
  126. DestinationCidrBlock: ‘0.0.0.0/0’
  127. GatewayId: !Ref ‘InternetGateway’
  128. RouteTableId: !Ref ‘PublicRouteTable’
  129.  
  130. PrivateSubnet1:
  131. Type: AWS::EC2::Subnet
  132. Properties:
  133. CidrBlock: !Ref ‘PrivateSubnetCIDR1’
  134. AvailabilityZone: !Select
  135. – ‘0’
  136. – !GetAZs ”
  137. MapPublicIpOnLaunch: ‘false’
  138. Tags:
  139. – Key: Name
  140. Value: Private Subnet 1
  141. VpcId: !Ref ‘VPC’
  142. PrivateSubnet2:
  143. Type: AWS::EC2::Subnet
  144. Properties:
  145. CidrBlock: !Ref ‘PrivateSubnetCIDR2’
  146. AvailabilityZone: !Select
  147. – ‘1’
  148. – !GetAZs ”
  149. MapPublicIpOnLaunch: ‘false’
  150. Tags:
  151. – Key: Name
  152. Value: Private Subnet 2
  153. VpcId: !Ref ‘VPC’
  154. PrivateSubnet3:
  155. Type: AWS::EC2::Subnet
  156. Properties:
  157. CidrBlock: !Ref ‘PrivateSubnetCIDR3’
  158. AvailabilityZone: !Select
  159. – ‘2’
  160. – !GetAZs ”
  161. MapPublicIpOnLaunch: ‘false’
  162. Tags:
  163. – Key: Name
  164. Value: Private Subnet 3
  165. VpcId: !Ref ‘VPC’
  166.  
  167. PrivateRouteTable1:
  168. Type: AWS::EC2::RouteTable
  169. Properties:
  170. VpcId: !Ref ‘VPC’
  171. Tags:
  172. – Key: Name
  173. Value: Private Route Table 1
  174. AttachPrivateSubnet1RouteTable1:
  175. Type: AWS::EC2::SubnetRouteTableAssociation
  176. Properties:
  177. RouteTableId: !Ref ‘PrivateRouteTable1’
  178. SubnetId: !Ref ‘PrivateSubnet1’
  179. AttachPrivateSubnet2RouteTable1:
  180. Type: AWS::EC2::SubnetRouteTableAssociation
  181. Properties:
  182. RouteTableId: !Ref ‘PrivateRouteTable1’
  183. SubnetId: !Ref ‘PrivateSubnet2’
  184. AttachPrivateSubnet3RouteTable1:
  185. Type: AWS::EC2::SubnetRouteTableAssociation
  186. Properties:
  187. RouteTableId: !Ref ‘PrivateRouteTable1’
  188. SubnetId: !Ref ‘PrivateSubnet3’
  189. PublicRoutetoInternet:
  190. Type: AWS::EC2::Route
  191. Properties:
  192. DestinationCidrBlock: ‘0.0.0.0/0’
  193. GatewayId: !Ref ‘InternetGateway’
  194. RouteTableId: !Ref ‘PrivateRouteTable1’
  195.  
  196.  
  197. Outputs:
  198. VPCID:
  199. Description: VPC ID
  200. Value: !Ref ‘VPC’
  201. Export:
  202. Name: !Sub ‘VPC’
  203. VPCCidrBlock:
  204. Description: VPC Cidr Block
  205. Value: !Ref ‘VPCCidrBlock’
  206. Export:
  207. Name: !Sub ‘${AWS::StackName}-VPCCidrBlock’
  208. PublicSubnet1:
  209. Description: Public Subnet 1
  210. Value: !Ref ‘PublicSubnet1’
  211. Export:
  212. Name: !Sub ‘${AWS::StackName}-public-subnet-1’
  213. PublicSubnet2:
  214. Description: Public Subnet 2
  215. Value: !Ref ‘PublicSubnet2’
  216. Export:
  217. Name: !Sub ‘${AWS::StackName}-public-subnet-2’
  218. PublicSubnet3:
  219. Description: Public Subnet 3
  220. Value: !Ref ‘PublicSubnet3’
  221. Export:
  222. Name: !Sub ‘${AWS::StackName}-public-subnet-3’
  223. PrivateSubnet1:
  224. Description: Private Subnet 1
  225. Value: !Ref ‘PrivateSubnet1’
  226. Export:
  227. Name: !Sub ‘${AWS::StackName}-private-subnet-1’
  228. PrivateSubnet2:
  229. Description: Private Subnet 2
  230. Value: !Ref ‘PrivateSubnet2’
  231. Export:
  232. Name: !Sub ‘${AWS::StackName}-private-subnet-2’
  233. PrivateSubnet3:
  234. Description: Private Subnet 3
  235. Value: !Ref ‘PrivateSubnet3’
  236. Export:
  237. Name: !Sub ‘${AWS::StackName}-private-subnet-3’
  238.  
Pawan Rai
DevOps Engineer at SprigHub
Cookie Value: