Last active
November 5, 2022 05:31
-
-
Save mikesparr/2939a97fdfa24ff5fa4cad9400b067e0 to your computer and use it in GitHub Desktop.
Freeswitch example on Google Cloud Platform
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
export PROJECT_ID=$(gcloud config get-value project) | |
export PROJECT_USER=$(gcloud config get-value core/account) # set current user | |
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)") | |
export IDNS=${PROJECT_ID}.svc.id.goog # workflow identity domain | |
export GCP_REGION="us-central1" # CHANGEME (OPT) | |
export GCP_ZONE="us-central1-a" # CHANGEME (OPT) | |
export NETWORK_NAME="default" | |
# enable apis | |
gcloud services enable compute.googleapis.com \ | |
iap.googleapis.com \ | |
storage.googleapis.com | |
gcloud config set compute/region $GCP_REGION | |
gcloud config set compute/zone $GCP_ZONE | |
########################################### | |
# IP ADDRESSES | |
########################################### | |
export NAT_GW_IP="nat-gw-ip" | |
export LOAD_BALANCER_IP="load-balancer-ip" | |
gcloud compute addresses create $NAT_GW_IP --region $GCP_REGION | |
gcloud compute addresses create $LOAD_BALANCER_IP --region $GCP_REGION | |
########################################### | |
# NAT GATEWAY | |
########################################### | |
export CLOUD_ROUTER_NAME="router-1" | |
export CLOUD_ROUTER_ASN="64523" | |
export NAT_GW_NAME="nat-gateway-1" | |
# create cloud router and nat gateway | |
gcloud compute routers create $CLOUD_ROUTER_NAME \ | |
--network $NETWORK_NAME \ | |
--asn $CLOUD_ROUTER_ASN \ | |
--region $GCP_REGION | |
gcloud compute routers nats create $NAT_GW_NAME \ | |
--router=$CLOUD_ROUTER_NAME \ | |
--region=$GCP_REGION \ | |
--auto-allocate-nat-external-ips \ | |
--nat-all-subnet-ip-ranges \ | |
--enable-logging | |
# change to static IP (test) | |
gcloud compute routers nats update $NAT_GW_NAME \ | |
--router=$CLOUD_ROUTER_NAME \ | |
--nat-external-ip-pool=$NAT_GW_IP | |
########################################### | |
# TEMPLATE + MIG + STARTUP SCRIPT | |
# | |
# debug on VM: | |
# - re-run startup: sudo google_metadata_script_runner startup | |
# - debug: sudo journalctl -u google-startup-scripts.service | |
########################################### | |
export TEMPLATE_NAME="freeswitch" | |
export GROUP_NAME="freeswitch" | |
export NW_TAG="freeswitch" | |
export BUCKET_NAME="mike-test-freeswitch-bucket" | |
export SCRIPT_NAME="startup.sh" | |
export COMPUTE_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" | |
# enable apis | |
gcloud services enable compute.googleapis.com \ | |
storage.googleapis.com \ | |
iap.googleapis.com | |
# create storage bucket | |
gsutil mb gs://$BUCKET_NAME | |
# add IAM permissions to bucket | |
gsutil iam ch serviceAccount:${COMPUTE_SA}:roles/storage.objectViewer gs://$BUCKET_NAME | |
# create startup script | |
# https://freeswitch.org/confluence/display/FREESWITCH/Debian+10+Buster | |
# | |
cat > startup.sh << EOF | |
#!/usr/bin/env bash | |
echo "[startup] Configuring FreeSWITCH server ..." | |
echo | |
echo "[startup] Updating packages ..." | |
apt-get update && apt-get install -y gnupg2 wget | |
wget -O - https://files.freeswitch.org/repo/deb/debian-release/fsstretch-archive-keyring.asc | apt-key add - | |
echo "deb http://files.freeswitch.org/repo/deb/debian-release/ buster main" > /etc/apt/sources.list.d/freeswitch.list | |
echo "deb-src http://files.freeswitch.org/repo/deb/debian-release/ buster main" >> /etc/apt/sources.list.d/freeswitch.list | |
echo "[startup] Checking sources file ..." | |
cat /etc/apt/sources.list.d/freeswitch.list | |
# if /etc/freeswitch does not exist, the standard vanilla configuration is deployed | |
echo "[startup] Installing FreeSWITCH ..." | |
apt-get update && apt-get install -y freeswitch-meta-all | |
# wait for config files to exist | |
echo "[startup] Waiting for config files ..." | |
while read i; do if [ "" = /etc/freeswitch/vars.xml ]; then break; fi; done < <(inotifywait -e create,open --format '%f' --quiet /tmp --monitor) | |
# TODO: edit config files to use correct IP addresses | |
# <X-PRE-PROCESS cmd="exec-set" data="external_rtp_ip=curl -X GET -H 'Metadata-Flavor: Google' 'http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip'"/> | |
echo "[startup] Editing config files ..." | |
echo "[startup] Done!" | |
exit 0 | |
EOF | |
# push script to bucket | |
gsutil cp ./$SCRIPT_NAME "gs://${BUCKET_NAME}/${SCRIPT_NAME}" | |
# create instance template w/ freeswitch install setup script | |
gcloud beta compute --project=$PROJECT_ID instance-templates create $TEMPLATE_NAME \ | |
--machine-type=e2-medium \ | |
--network=projects/mike-test-freeswitch/global/networks/default \ | |
--network-tier=PREMIUM \ | |
--metadata="startup-script-url=gs://${BUCKET_NAME}/${SCRIPT_NAME}" \ | |
--can-ip-forward \ | |
--no-address \ | |
--service-account=733678248239-compute@developer.gserviceaccount.com \ | |
--scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append \ | |
--tags=$NW_TAG \ | |
--image=debian-10-buster-v20210420 \ | |
--image-project=debian-cloud \ | |
--boot-disk-size=10GB \ | |
--boot-disk-type=pd-balanced \ | |
--boot-disk-device-name=$GROUP_NAME \ | |
--shielded-secure-boot \ | |
--no-shielded-vtpm \ | |
--no-shielded-integrity-monitoring \ | |
--labels=role=pbx \ | |
--reservation-affinity=any | |
# create instance group | |
gcloud compute --project=$PROJECT_ID instance-groups managed create $GROUP_NAME \ | |
--base-instance-name=$GROUP_NAME \ | |
--template=$GROUP_NAME \ | |
--size=2 \ | |
--zone=$GCP_ZONE | |
# configure autoscaler (can increase to 2 min for testing) | |
gcloud beta compute --project $PROJECT_ID instance-groups managed set-autoscaling $GROUP_NAME \ | |
--zone $GCP_ZONE \ | |
--cool-down-period "60" \ | |
--max-num-replicas "5" \ | |
--min-num-replicas "1" \ | |
--target-cpu-utilization "0.85" \ | |
--mode "on" | |
################################################# | |
# LOAD BALANCING | |
################################################# | |
# create health check | |
gcloud compute health-checks create tcp tcp-health-check \ | |
--region $GCP_REGION \ | |
--port 5060 | |
# create firewall rules for health checks | |
gcloud compute firewall-rules create fw-allow-network-lb-health-checks \ | |
--action=ALLOW \ | |
--direction=INGRESS \ | |
--source-ranges=35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ | |
--rules=tcp | |
# create firewall rules for FreeSwitch | |
export FW_PORTS="UDP:1719,TCP:1720,TCP:2855-2856,UDP:3478-3479,TCP:5002-5003,UDP:5060,TCP:5060,UDP:5070,TCP:5070,UDP:5080,TCP:5080,UDP:16384-32768,TCP:5066,TCP:7443,TCP:8081-8082" | |
gcloud compute firewall-rules create freeswitch-policy \ | |
--allow $FW_PORTS \ | |
--source-ranges=0.0.0.0/0 \ | |
--target-tags=$NW_TAG | |
# create backend service | |
gcloud compute backend-services create network-lb-backend-service \ | |
--protocol TCP \ | |
--health-checks tcp-health-check \ | |
--health-checks-region $GCP_REGION \ | |
--region $GCP_REGION | |
# add instance group to backend | |
gcloud compute backend-services add-backend network-lb-backend-service \ | |
--instance-group $GROUP_NAME \ | |
--instance-group-zone $GCP_ZONE \ | |
--region $GCP_REGION | |
# add forwarding rule | |
gcloud compute forwarding-rules create network-lb-forwarding-rule \ | |
--load-balancing-scheme external \ | |
--region $GCP_REGION \ | |
--ports 1-65535 \ | |
--address $LOAD_BALANCER_IP \ | |
--backend-service network-lb-backend-service | |
############################################# | |
# IAP ACCESS | |
############################################# | |
# grant SSH access | |
gcloud compute firewall-rules create allow-ssh-ingress-from-iap \ | |
--direction=INGRESS \ | |
--action=allow \ | |
--rules=tcp:22 \ | |
--source-ranges=35.235.240.0/20 | |
# grant user tunneling (one for each user or group [preferred]) | |
gcloud projects add-iam-policy-binding $PROJECT_ID \ | |
--member=user:$PROJECT_USER \ | |
--role=roles/iap.tunnelResourceAccessor | |
# TODO: fetch name of compute instance | |
# connect with IAP tunnel SSH into private VM | |
gcloud compute ssh freeswitch-private \ | |
--zone $GCP_ZONE \ | |
--tunnel-through-iap | |
# ... |
Hi Mike,
Have you tried to use TLS connections to FreeSWITCH using Google's SSL LB?
Any luck with this? I've been struggling with it for the past week.
I haven't revisited the original experiment and I believe some used Kamailio or another proxy to solve the NAT issue. If someone was more of a FreeSwitch guru, they might know the levers in configs to address NAT issue. Unfortunately I didn't solve that part.
No I did not try HTTPS LB which supports ports 80/443, nor the SSL Proxy which I don't believe supports needed ports, only the L4 (TCP) load balancer.
Original experiment here: https://gist.github.com/mikesparr/e3a06763e2f67735f96e6940eedb055e
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If I edit the instance template and deploy an instance group with external IPs, 2-way SIP + RTP (audio) works.
If the template has
--no-address
flag and internal IP only, using NAT, then SIP works but RTP does not (no audio).