New proxy example
This commit is contained in:
parent
6c08ec012d
commit
5f65fec044
|
@ -0,0 +1,16 @@
|
||||||
|
# Network filtering with Squid
|
||||||
|
|
||||||
|
This example shows how to deploy a filtering HTTP proxy to restrict Internet access. Here we show one way to do this using a VPC with two subnets:
|
||||||
|
|
||||||
|
- The first subnet (called "apps" in this example) hosts the VMs that will have their Internet access tightly controlled a non-caching filtering forward proxy.
|
||||||
|
- The second subnet (called "proxy" in this example) hosts a Cloud NAT instance and a Squid Server [Squid](http://www.squid-cache.org/).
|
||||||
|
|
||||||
|
The VPC is a Shared VPC and all the service projects will be located under a folder enforcing the `compute.vmExternalIpAccess` (organization policies)[https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints]. This prevents the service projects from having external IPs thus forcing all outbound Internet connections through the proxy.
|
||||||
|
|
||||||
|
To allow Internet connectivity to the proxy subnet, a Cloud NAT instance is configured to allow usage from (that subnet only)[https://cloud.google.com/nat/docs/using-nat#specify_subnet_ranges_for_nat]. All other subnets are not allowed to use the Cloud NAT instance.
|
||||||
|
|
||||||
|
To simplify the usage of the proxy, a Cloud DNS private zone is created and the IP address of the proxy is exposed with the FQDN `proxy.internal`.
|
||||||
|
|
||||||
|
You can optionally deploy the Squid server as (Managed Instance Group)[https://cloud.google.com/compute/docs/instance-groups] by setting the `mig` option to `true`. This option defaults to `false` which results in a standalone VM.
|
||||||
|
|
||||||
|
![High-level diagram](squid.png "High-level diagram")
|
|
@ -0,0 +1,245 @@
|
||||||
|
locals {
|
||||||
|
squid_address = (
|
||||||
|
var.mig
|
||||||
|
? module.squid-ilb.0.forwarding_rule_address
|
||||||
|
: module.squid-vm.internal_ips.0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Top level folder #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
module "folder-netops" {
|
||||||
|
source = "../../modules/folder"
|
||||||
|
parent = var.root_node
|
||||||
|
name = "netops"
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Host project and shared VPC resources #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
module "project-host" {
|
||||||
|
source = "../../modules/project"
|
||||||
|
billing_account = var.billing_account
|
||||||
|
name = "host"
|
||||||
|
parent = module.folder-netops.id
|
||||||
|
prefix = var.prefix
|
||||||
|
services = [
|
||||||
|
"compute.googleapis.com",
|
||||||
|
"dns.googleapis.com",
|
||||||
|
"logging.googleapis.com"
|
||||||
|
]
|
||||||
|
shared_vpc_host_config = {
|
||||||
|
enabled = true
|
||||||
|
service_projects = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "vpc" {
|
||||||
|
source = "../../modules/net-vpc"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
name = "vpc"
|
||||||
|
subnets = [
|
||||||
|
{
|
||||||
|
name = "apps"
|
||||||
|
ip_cidr_range = var.cidrs.apps
|
||||||
|
region = var.region
|
||||||
|
secondary_ip_range = null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "proxy"
|
||||||
|
ip_cidr_range = var.cidrs.proxy
|
||||||
|
region = var.region
|
||||||
|
secondary_ip_range = null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
module "firewall" {
|
||||||
|
source = "../../modules/net-vpc-firewall"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
network = module.vpc.name
|
||||||
|
custom_rules = {
|
||||||
|
allow-ingress-squid = {
|
||||||
|
description = "Allow squid ingress traffic"
|
||||||
|
direction = "INGRESS"
|
||||||
|
action = "allow"
|
||||||
|
sources = []
|
||||||
|
ranges = [var.cidrs.apps, "35.191.0.0/16", "130.211.0.0/22"]
|
||||||
|
targets = [module.service-account-squid.email]
|
||||||
|
use_service_accounts = true
|
||||||
|
rules = [{ protocol = "tcp", ports = [3128] }]
|
||||||
|
extra_attributes = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "nat" {
|
||||||
|
source = "../../modules/net-cloudnat"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
region = var.region
|
||||||
|
name = "default"
|
||||||
|
router_network = module.vpc.name
|
||||||
|
config_source_subnets = "LIST_OF_SUBNETWORKS"
|
||||||
|
# 64512/11 = 5864 . 11 is the number of usable IPs in the proxy subnet
|
||||||
|
config_min_ports_per_vm = 5864
|
||||||
|
subnetworks = [
|
||||||
|
{
|
||||||
|
self_link = module.vpc.subnet_self_links["${var.region}/proxy"]
|
||||||
|
config_source_ranges = ["ALL_IP_RANGES"]
|
||||||
|
secondary_ranges = null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
logging_filter = var.nat_logging
|
||||||
|
}
|
||||||
|
|
||||||
|
module "service-account-squid" {
|
||||||
|
source = "../../modules/iam-service-account"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
name = "svc-squid"
|
||||||
|
iam_project_roles = {
|
||||||
|
(module.project-host.project_id) = [
|
||||||
|
"roles/logging.logWriter",
|
||||||
|
"roles/monitoring.metricWriter",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "cos-squid" {
|
||||||
|
source = "../../modules/cloud-config-container/squid"
|
||||||
|
allow = [
|
||||||
|
".github.com",
|
||||||
|
]
|
||||||
|
clients = [var.cidrs.apps]
|
||||||
|
}
|
||||||
|
|
||||||
|
module "squid-vm" {
|
||||||
|
source = "../../modules/compute-vm"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
region = var.region
|
||||||
|
name = "squid-vm"
|
||||||
|
instance_type = "e2-medium"
|
||||||
|
network_interfaces = [{
|
||||||
|
network = module.vpc.self_link
|
||||||
|
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
|
||||||
|
nat = false
|
||||||
|
addresses = null
|
||||||
|
alias_ips = null
|
||||||
|
}]
|
||||||
|
boot_disk = {
|
||||||
|
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||||
|
type = "pd-standard"
|
||||||
|
size = 15
|
||||||
|
}
|
||||||
|
service_account = module.service-account-squid.email
|
||||||
|
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
|
||||||
|
use_instance_template = var.mig
|
||||||
|
metadata = {
|
||||||
|
user-data = module.cos-squid.cloud_config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "squid-mig" {
|
||||||
|
count = var.mig ? 1 : 0
|
||||||
|
source = "../../modules/compute-mig"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
location = "${var.region}-b"
|
||||||
|
name = "squid-mig"
|
||||||
|
target_size = 1
|
||||||
|
autoscaler_config = {
|
||||||
|
max_replicas = 10
|
||||||
|
min_replicas = 1
|
||||||
|
cooldown_period = 30
|
||||||
|
cpu_utilization_target = 0.65
|
||||||
|
load_balancing_utilization_target = null
|
||||||
|
metric = null
|
||||||
|
}
|
||||||
|
default_version = {
|
||||||
|
instance_template = module.squid-vm.template.self_link
|
||||||
|
name = "default"
|
||||||
|
}
|
||||||
|
health_check_config = {
|
||||||
|
type = "tcp"
|
||||||
|
check = { port = 3128 }
|
||||||
|
config = {}
|
||||||
|
logging = true
|
||||||
|
}
|
||||||
|
auto_healing_policies = {
|
||||||
|
health_check = module.squid-mig.0.health_check.self_link
|
||||||
|
initial_delay_sec = 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "squid-ilb" {
|
||||||
|
count = var.mig ? 1 : 0
|
||||||
|
source = "../../modules/net-ilb"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
region = var.region
|
||||||
|
name = "squid-ilb"
|
||||||
|
service_label = "squid-ilb"
|
||||||
|
network = module.vpc.self_link
|
||||||
|
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
|
||||||
|
ports = [3128]
|
||||||
|
backends = [{
|
||||||
|
failover = false
|
||||||
|
group = module.squid-mig.0.group_manager.instance_group
|
||||||
|
balancing_mode = "CONNECTION"
|
||||||
|
}]
|
||||||
|
health_check_config = {
|
||||||
|
type = "tcp"
|
||||||
|
check = { port = 3128 }
|
||||||
|
config = {}
|
||||||
|
logging = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "private-dns" {
|
||||||
|
source = "../../modules/dns"
|
||||||
|
project_id = module.project-host.project_id
|
||||||
|
type = "private"
|
||||||
|
name = "internal"
|
||||||
|
domain = "internal."
|
||||||
|
client_networks = [module.vpc.self_link]
|
||||||
|
recordsets = [
|
||||||
|
{
|
||||||
|
name = "squid"
|
||||||
|
type = "A"
|
||||||
|
ttl = 60
|
||||||
|
records = [local.squid_address]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Service project #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
module "folder-apps" {
|
||||||
|
source = "../../modules/folder"
|
||||||
|
parent = var.root_node
|
||||||
|
name = "apps"
|
||||||
|
policy_list = {
|
||||||
|
# prevent VMs with public IPs in the apps folder
|
||||||
|
"constraints/compute.vmExternalIpAccess" = {
|
||||||
|
inherit_from_parent = false
|
||||||
|
suggested_value = null
|
||||||
|
status = false
|
||||||
|
values = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "project-app" {
|
||||||
|
source = "../../modules/project"
|
||||||
|
billing_account = var.billing_account
|
||||||
|
name = "app"
|
||||||
|
parent = module.folder-apps.id
|
||||||
|
prefix = var.prefix
|
||||||
|
services = ["compute.googleapis.com"]
|
||||||
|
shared_vpc_service_config = {
|
||||||
|
attach = true
|
||||||
|
host_project = module.project-host.project_id
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
output "squid-address" {
|
||||||
|
value = local.squid_address
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
|
@ -0,0 +1,40 @@
|
||||||
|
variable "billing_account" {
|
||||||
|
description = "Billing account id used as default for new projects."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "prefix" {
|
||||||
|
description = "Prefix used for resources that need unique names."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "root_node" {
|
||||||
|
description = "Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "region" {
|
||||||
|
description = "Default region for resources"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "cidrs" {
|
||||||
|
description = "CIDR ranges for subnets"
|
||||||
|
type = map(string)
|
||||||
|
default = {
|
||||||
|
apps = "10.0.0.0/24"
|
||||||
|
proxy = "10.0.1.0/28"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "nat_logging" {
|
||||||
|
description = "Enables Cloud NAT logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'."
|
||||||
|
type = string
|
||||||
|
default = "ERRORS_ONLY"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "mig" {
|
||||||
|
description = "Enables the creation of an autoscaling managed instance group of squid instances."
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
Loading…
Reference in New Issue