diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.ym similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/ci.ym diff --git a/FAQ.md b/FAQ.md index cac9412f..30c2af96 100644 --- a/FAQ.md +++ b/FAQ.md @@ -10,7 +10,7 @@ git clone https://github.com/WhatsApp/proxy.git ## Common issues -### (1) The container won't build on Windows with `set_public_ip_and_start.sh: Not found` +### (1) The container won't build on Windows with `start.sh: Not found` This is likely a line encoding issue since the application is expecting unix-style line encoding (EOL not CRLF). This resolved in PR [72](https://github.com/WhatsApp/proxy/pull/72) diff --git a/README.md b/README.md index 4f778205..c78dd222 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,23 @@ on connections. If you have a network load balancer you can preserve the client 2. 8443: Standard web traffic, encrypted (HTTPS) with PROXY protocol expected 3. 8222: Jabber protocol traffic (WhatsApp default) with PROXY protocol expected +## Adverse network conditions + +The proxy container exposes many ports for different functionality. +When deploying the container to work around adverse network conditions, +this flexibility may actually be undesirable, +since a proxy instance may be uniquely identified by some of the non-standard ports. + +To provide basic functionality (messages and media), +we recommend exposing only ports 443 and 587 on the proxy endpoint. + +This is required **only if exposing the proxy on a public IP address**, +and not needed for users connecting to the proxy through a VPN or a private connection. + +> Note: When using the proxy enabled HTTPS port (8443), +> make sure port 8443 is exposed publicly as port 443, +> to ensure WhatsApp clients can connect to port 443. + ## Certificate generation for SSL encrypted ports Ports 443 and 8443 are protected by a self-signed encryption certificate generated at container start time. There are some custom options should you wish to tweak the settings of the generated certificates diff --git a/charts/whatsapp-proxy-chart/Chart.yaml b/charts/whatsapp-proxy-chart/Chart.yaml index 2e1340c5..ec849ec7 100644 --- a/charts/whatsapp-proxy-chart/Chart.yaml +++ b/charts/whatsapp-proxy-chart/Chart.yaml @@ -17,7 +17,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.1.0 +version: 1.3.12 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/whatsapp-proxy-chart/templates/configmap.yaml b/charts/whatsapp-proxy-chart/templates/configmap.yaml new file mode 100644 index 00000000..10ca845b --- /dev/null +++ b/charts/whatsapp-proxy-chart/templates/configmap.yaml @@ -0,0 +1,13 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# License found in the LICENSE file in the root directory +# of this source tree. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "whatsapp-proxy-chart.fullname" . }}-haproxy + labels: + {{- include "whatsapp-proxy-chart.labels" . | nindent 4 }} +data: + haproxy.cfg: | + {{- tpl .Values.haproxyConfig . | nindent 4 }} diff --git a/charts/whatsapp-proxy-chart/templates/deployment.yaml b/charts/whatsapp-proxy-chart/templates/deployment.yaml index d0206772..40f8f1b3 100644 --- a/charts/whatsapp-proxy-chart/templates/deployment.yaml +++ b/charts/whatsapp-proxy-chart/templates/deployment.yaml @@ -17,10 +17,11 @@ spec: {{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} annotations: + checksum/haproxy-config: {{ tpl .Values.haproxyConfig . | sha256sum }} + {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} labels: {{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 8 }} spec: @@ -38,41 +39,33 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - {{- if .Values.service.http_proxy_port }} - name: http-proxy containerPort: 8080 protocol: TCP - {{- end}} - {{- if .Values.service.http_port }} - name: http containerPort: 80 protocol: TCP - {{- end}} - {{- if .Values.service.https_proxy_port }} - name: https-proxy containerPort: 8443 protocol: TCP - {{- end}} - {{- if .Values.service.https_port }} - name: https containerPort: 443 protocol: TCP - {{- end}} - {{- if .Values.service.jabber_proxy_port }} - name: jabber-proxy containerPort: 8222 protocol: TCP - {{- end}} - {{- if .Values.service.jabber_port }} - name: jabber containerPort: 5222 protocol: TCP - {{- end}} - {{- if .Values.service.stats_port }} + - name: media + containerPort: 587 + protocol: TCP + - name: media-proxy + containerPort: 7777 + protocol: TCP - name: stats containerPort: 8199 protocol: TCP - {{- end}} readinessProbe: exec: command: @@ -81,9 +74,25 @@ spec: periodSeconds: 30 resources: {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.extraEnv }} env: - - name: "PUBLIC_IP" - value: "{{ .Values.public_ip }}" + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: haproxy-config + mountPath: /usr/local/etc/haproxy/haproxy.cfg + subPath: haproxy.cfg + readOnly: true + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: haproxy-config + configMap: + name: {{ include "whatsapp-proxy-chart.fullname" . }}-haproxy + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/charts/whatsapp-proxy-chart/templates/hpa.yaml b/charts/whatsapp-proxy-chart/templates/hpa.yaml index e127efa1..4f6f1fca 100644 --- a/charts/whatsapp-proxy-chart/templates/hpa.yaml +++ b/charts/whatsapp-proxy-chart/templates/hpa.yaml @@ -3,7 +3,7 @@ # License found in the LICENSE file in the root directory # of this source tree. {{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 +apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: {{ include "whatsapp-proxy-chart.fullname" . }} @@ -21,12 +21,19 @@ spec: - type: Resource resource: name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} {{- end }} {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- with .Values.autoscaling.customMetrics }} + {{- toYaml . | nindent 4 }} {{- end }} {{- end }} diff --git a/charts/whatsapp-proxy-chart/templates/service.yaml b/charts/whatsapp-proxy-chart/templates/service.yaml index c4b154d9..19bd15c2 100644 --- a/charts/whatsapp-proxy-chart/templates/service.yaml +++ b/charts/whatsapp-proxy-chart/templates/service.yaml @@ -15,6 +15,9 @@ metadata: spec: type: {{ .Values.service.type }} + {{- with .Values.service.loadBalancerClass }} + loadBalancerClass: {{ . | quote }} + {{- end }} ports: {{- if .Values.service.http_proxy_port }} - port: {{ .Values.service.http_proxy_port }} @@ -64,7 +67,6 @@ spec: protocol: TCP name: media {{- end}} - {{- if .Values.service.media_proxy_port }} - port: {{ .Values.service.media_proxy_port }} targetPort: 7777 diff --git a/charts/whatsapp-proxy-chart/templates/servicemonitor.yaml b/charts/whatsapp-proxy-chart/templates/servicemonitor.yaml new file mode 100644 index 00000000..8a85f1fb --- /dev/null +++ b/charts/whatsapp-proxy-chart/templates/servicemonitor.yaml @@ -0,0 +1,24 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# License found in the LICENSE file in the root directory +# of this source tree. +{{- if .Values.enableServiceMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "whatsapp-proxy-chart.fullname" . }}-servicemonitor + namespace: default + labels: + release: {{ .Values.prometheus.release }} +spec: + endpoints: + - interval: 30s + path: /metrics + port: stats + namespaceSelector: + matchNames: + - default + selector: + matchLabels: + {{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/whatsapp-proxy-chart/templates/tests/test-connection.yaml b/charts/whatsapp-proxy-chart/templates/tests/test-connection.yaml index c2f174ed..7c6d3e50 100644 --- a/charts/whatsapp-proxy-chart/templates/tests/test-connection.yaml +++ b/charts/whatsapp-proxy-chart/templates/tests/test-connection.yaml @@ -6,10 +6,12 @@ apiVersion: v1 kind: Pod metadata: name: "{{ include "whatsapp-proxy-chart.fullname" . }}-test-connection" - labels: - {{- include "whatsapp-proxy-chart.labels" . | nindent 4 }} + # Intentionally omit common/selector labels so this pod is not matched by the + # HPA's selector. This test pod has no resource requests, and including it + # would break the HPA's utilization calculation. annotations: "helm.sh/hook": test + "helm.sh/hook-delete-policy": hook-succeeded spec: containers: - name: wget diff --git a/charts/whatsapp-proxy-chart/values.yaml b/charts/whatsapp-proxy-chart/values.yaml index 52bab0c0..0aeb635b 100644 --- a/charts/whatsapp-proxy-chart/values.yaml +++ b/charts/whatsapp-proxy-chart/values.yaml @@ -15,8 +15,6 @@ image: # Overrides the image tag whose default is the chart appVersion. tag: "latest" -public_ip: "10.0.0.1" - imagePullSecrets: {} nameOverride: "" fullnameOverride: "" @@ -96,9 +94,172 @@ autoscaling: maxReplicas: 100 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 + customMetrics: [] nodeSelector: {} tolerations: [] affinity: {} + +# Extra volumes to attach to the pod, rendered as-is into the Deployment's +# spec.template.spec.volumes +extraVolumes: [] + +# Extra volumeMounts for the HAProxy container. +extraVolumeMounts: [] + +# Extra environment variables for the HAProxy container. This can be used to +# inject secrets with valueFrom.secretKeyRef without putting them in values. +extraEnv: [] + +enableServiceMonitor: false +prometheus: + release: my-prometheus-release + +# HAProxy tunables. These are interpolated into haproxyConfig below via `tpl`, +# so individual values (e.g. maxconn) can be overridden per-deployment without +# replacing the entire config blob. +haproxy: + global: + tuneBufsize: 4096 + maxconn: 27500 + spreadChecks: 5 + sslServerVerify: none + defaults: + mode: tcp + timeoutClientFin: 1s + timeoutServerFin: 1s + timeoutConnect: 5s + timeoutClient: 200s + timeoutServer: 200s + defaultServer: inter 10s fastinter 1s downinter 3s error-limit 50 + stats: + bind: ":::8199" + mode: http + metricsPath: /metrics + uri: / + frontends: + haproxyV4Http: + maxconn: 27495 + directBind: ipv4@*:80 + proxyBind: ipv4@*:8080 accept-proxy + config: [] + defaultBackend: wa + haproxyV4Https: + maxconn: 27495 + directBind: ipv4@*:443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem + proxyBind: ipv4@*:8443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem accept-proxy + config: [] + defaultBackend: wa + haproxyV4Xmpp: + maxconn: 27495 + directBind: ipv4@*:5222 + proxyBind: ipv4@*:8222 accept-proxy + config: [] + defaultBackend: wa + haproxyV4WhatsappNet: + maxconn: 27495 + directBind: ipv4@*:587 + proxyBind: ipv4@*:7777 + config: [] + defaultBackend: wa_whatsapp_net + backends: + waWhatsappNet: + defaultServer: check inter 60000 observe layer4 + serverName: whatsapp_net_443 + serverAddress: whatsapp.net:443 + wa: + defaultServer: check inter 60000 observe layer4 send-proxy-v2 + servers: + - name: g_whatsapp_net_5222 + address: g.whatsapp.net:5222 + - name: g_whatsapp_net_80 + address: g.whatsapp.net:80 + - name: g_whatsapp_net_443 + address: g.whatsapp.net:443 + - name: g_fallback_whatsapp_net_5222 + address: g-fallback.whatsapp.net:5222 + - name: g_fallback_whatsapp_net_80 + address: g-fallback.whatsapp.net:80 + - name: g_fallback_whatsapp_net_443 + address: g-fallback.whatsapp.net:443 + +# HAProxy configuration file contents, rendered through `tpl` so the values +# under `haproxy:` above are interpolated. Edit haproxy.* values (or override +# them per-deployment) to customize proxy behavior without rebuilding the image. +haproxyConfig: | + global + tune.bufsize {{ .Values.haproxy.global.tuneBufsize }} + maxconn {{ .Values.haproxy.global.maxconn }} + spread-checks {{ .Values.haproxy.global.spreadChecks }} + ssl-server-verify {{ .Values.haproxy.global.sslServerVerify }} + + defaults + mode {{ .Values.haproxy.defaults.mode }} + timeout client-fin {{ .Values.haproxy.defaults.timeoutClientFin }} + timeout server-fin {{ .Values.haproxy.defaults.timeoutServerFin }} + timeout connect {{ .Values.haproxy.defaults.timeoutConnect }} + timeout client {{ .Values.haproxy.defaults.timeoutClient }} + timeout server {{ .Values.haproxy.defaults.timeoutServer }} + default-server {{ .Values.haproxy.defaults.defaultServer }} + + listen stats + bind {{ .Values.haproxy.stats.bind }} + mode {{ .Values.haproxy.stats.mode }} + http-request use-service prometheus-exporter if { path {{ .Values.haproxy.stats.metricsPath }} } + stats uri {{ .Values.haproxy.stats.uri }} + + frontend haproxy_v4_http + maxconn {{ .Values.haproxy.frontends.haproxyV4Http.maxconn }} + + bind {{ .Values.haproxy.frontends.haproxyV4Http.directBind }} + bind {{ .Values.haproxy.frontends.haproxyV4Http.proxyBind }} + {{- range .Values.haproxy.frontends.haproxyV4Http.config }} + {{ . }} + {{- end }} + + default_backend {{ .Values.haproxy.frontends.haproxyV4Http.defaultBackend }} + + frontend haproxy_v4_https + maxconn {{ .Values.haproxy.frontends.haproxyV4Https.maxconn }} + + bind {{ .Values.haproxy.frontends.haproxyV4Https.directBind }} + bind {{ .Values.haproxy.frontends.haproxyV4Https.proxyBind }} + {{- range .Values.haproxy.frontends.haproxyV4Https.config }} + {{ . }} + {{- end }} + + default_backend {{ .Values.haproxy.frontends.haproxyV4Https.defaultBackend }} + + frontend haproxy_v4_xmpp + maxconn {{ .Values.haproxy.frontends.haproxyV4Xmpp.maxconn }} + + bind {{ .Values.haproxy.frontends.haproxyV4Xmpp.directBind }} + bind {{ .Values.haproxy.frontends.haproxyV4Xmpp.proxyBind }} + {{- range .Values.haproxy.frontends.haproxyV4Xmpp.config }} + {{ . }} + {{- end }} + + default_backend {{ .Values.haproxy.frontends.haproxyV4Xmpp.defaultBackend }} + + frontend haproxy_v4_whatsapp_net + maxconn {{ .Values.haproxy.frontends.haproxyV4WhatsappNet.maxconn }} + + bind {{ .Values.haproxy.frontends.haproxyV4WhatsappNet.directBind }} + bind {{ .Values.haproxy.frontends.haproxyV4WhatsappNet.proxyBind }} + {{- range .Values.haproxy.frontends.haproxyV4WhatsappNet.config }} + {{ . }} + {{- end }} + + default_backend {{ .Values.haproxy.frontends.haproxyV4WhatsappNet.defaultBackend }} + + backend wa_whatsapp_net + default-server {{ .Values.haproxy.backends.waWhatsappNet.defaultServer }} + server {{ .Values.haproxy.backends.waWhatsappNet.serverName }} {{ .Values.haproxy.backends.waWhatsappNet.serverAddress }} + + backend wa + default-server {{ .Values.haproxy.backends.wa.defaultServer }} + {{- range .Values.haproxy.backends.wa.servers }} + server {{ .name }} {{ .address }} + {{- end }} diff --git a/proxy/Dockerfile b/proxy/Dockerfile index 288a45d9..da0d3561 100644 --- a/proxy/Dockerfile +++ b/proxy/Dockerfile @@ -22,9 +22,9 @@ RUN chmod +x /usr/local/bin/generate-certs.sh && \ chown -R haproxy:haproxy /etc/haproxy/ WORKDIR / -# Copy the public-ip setting + sshd startup script -COPY --chown=haproxy:haproxy src/set_public_ip_and_start.sh /usr/local/bin/set_public_ip_and_start.sh -RUN chmod +x /usr/local/bin/set_public_ip_and_start.sh +# Copy the startup script +COPY --chown=haproxy:haproxy src/start.sh /usr/local/bin/start.sh +RUN chmod +x /usr/local/bin/start.sh # Copy the HAProxy configuration COPY --chown=haproxy:haproxy src/proxy_config.cfg /usr/local/etc/haproxy/haproxy.cfg @@ -54,5 +54,5 @@ EXPOSE 8199/tcp EXPOSE 587/tcp EXPOSE 7777/tcp -# This is the startup command which also runs a background job to manage the WAPOX IPs -CMD /usr/local/bin/set_public_ip_and_start.sh +# Generate a runtime certificate and start HAProxy +CMD ["/usr/local/bin/start.sh"] diff --git a/proxy/ops/docker-compose.yml b/proxy/ops/docker-compose.yml index 811636a3..7659283b 100644 --- a/proxy/ops/docker-compose.yml +++ b/proxy/ops/docker-compose.yml @@ -23,5 +23,3 @@ services: test: /usr/local/bin/healthcheck.sh interval: 10s start_period: 5s - environment: - - PUBLIC_IP=10.0.0.1 diff --git a/proxy/src/healthcheck.sh b/proxy/src/healthcheck.sh index 0e651714..ca5b9eb0 100644 --- a/proxy/src/healthcheck.sh +++ b/proxy/src/healthcheck.sh @@ -11,7 +11,7 @@ curl -s -w 2 "http://127.0.0.1:8199/;csv" > /tmp/stats.txt || exit 1 # Filter out the lines for *.whatsapp_net backend status # Select the "check_desc" field (Description of the check result) # and take all results that do NOT equal "Layer4 check passed" from HAProxy -RESULT=$(tail -n +1 /tmp/stats.txt | jq -R 'split(",")' | jq -c '. | select(.[1] | contains("whatsapp_net"))' | jq --raw-output '.[65]| select(. | test("Layer4 check passed") | not)') +RESULT=$(tail -n +1 /tmp/stats.txt | jq -R 'split(",")' | jq -c 'select(.[1] != null) | select(.[1] | contains("whatsapp_net"))' | jq --raw-output '.[65]| select(. | test("Layer4 check passed") | not)') # # CSV output header row: # # ["# pxname","svname","qcur","qmax","scur","smax","slim","stot","bin","bout","dreq","dresp","ereq","econ","eresp","wretr","wredis","status","weight","act","bck","chkfail","chkdown","lastchg","downtime","qlimit","pid","iid","sid","throttle","lbtot","tracked","type","rate","rate_lim","rate_max","check_status","check_code","check_duration","hrsp_1xx","hrsp_2xx","hrsp_3xx","hrsp_4xx","hrsp_5xx","hrsp_other","hanafail","req_rate","req_rate_max","req_tot","cli_abrt","srv_abrt","comp_in","comp_out","comp_byp","comp_rsp","lastsess","last_chk","last_agt","qtime","ctime","rtime","ttime","agent_status","agent_code","agent_duration","check_desc","agent_desc","check_rise","check_fall","check_health","agent_rise","agent_fall","agent_health","addr","cookie","mode","algo","conn_rate","conn_rate_max","conn_tot","intercepted","dcon","dses","wrew","connect","reuse","cache_lookups","cache_hits","srv_icur","src_ilim","qtime_max","ctime_max","rtime_max","ttime_max","eint","idle_conn_cur","safe_conn_cur","used_conn_cur","need_conn_est","uweight","agg_server_check_status","-","ssl_sess","ssl_reused_sess","ssl_failed_handshake","h2_headers_rcvd","h2_data_rcvd","h2_settings_rcvd","h2_rst_stream_rcvd","h2_goaway_rcvd","h2_detected_conn_protocol_errors","h2_detected_strm_protocol_errors","h2_rst_stream_resp","h2_goaway_resp","h2_open_connections","h2_backend_open_streams","h2_total_connections","h2_backend_total_streams",""] @@ -24,4 +24,3 @@ then fi exit 0; - diff --git a/proxy/src/proxy_config.cfg b/proxy/src/proxy_config.cfg index 889d9913..236b3451 100644 --- a/proxy/src/proxy_config.cfg +++ b/proxy/src/proxy_config.cfg @@ -55,7 +55,6 @@ listen stats # connections frontend haproxy_v4_http maxconn 27495 - #PUBLIC_IP bind ipv4@*:80 bind ipv4@*:8080 accept-proxy @@ -64,7 +63,6 @@ frontend haproxy_v4_http frontend haproxy_v4_https maxconn 27495 - #PUBLIC_IP bind ipv4@*:443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem bind ipv4@*:8443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem accept-proxy @@ -73,7 +71,6 @@ frontend haproxy_v4_https frontend haproxy_v4_xmpp maxconn 27495 - #PUBLIC_IP bind ipv4@*:5222 bind ipv4@*:8222 accept-proxy @@ -82,7 +79,6 @@ frontend haproxy_v4_xmpp frontend haproxy_v4_whatsapp_net maxconn 27495 - #PUBLIC_IP bind ipv4@*:587 bind ipv4@*:7777 diff --git a/proxy/src/set_public_ip_and_start.sh b/proxy/src/set_public_ip_and_start.sh deleted file mode 100755 index 9ade79aa..00000000 --- a/proxy/src/set_public_ip_and_start.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# License found in the LICENSE file in the root directory -# of this source tree. - -## About: -# This script replaces instances of #PUBLIC_IP in the HaProxy configuration files -# with the real public ip. There's an order of priority here which is -# 1. Environment variable -# 2. AWS EC2 Metadata endpoint -# 3. Third-party sources -# If all fails, we'll just not set the destination IP address - -CONFIG_FILE="/usr/local/etc/haproxy/haproxy.cfg" - -## Custom function to use as curl wrapper -# --silent: to reduce the nois eof response -# --show-error: to show errors in the response -# --fail: to fail on non-200 responses -# --ipv4: to force ipv4 resolution -# --max-time: to set a timeout -function fetch() { - curl --silent --show-error --fail --ipv4 --max-time 2 "$@" -} - -## PUBLIC_IP supplied from environment variable -if [[ $PUBLIC_IP == '' ]] -then - echo "[PROXYHOST] No public IP address was supplied as an environment variable." -fi - -## PUBLIC_IP retrieved from AWS EC2 metadata endpoint -if [[ $PUBLIC_IP == '' ]] -then - # Attempt retrieval of the public ip from the meta-data instance - PUBLIC_IP=$(fetch http://169.254.169.254/latest/meta-data/public-ipv4) - if [[ $PUBLIC_IP == '' ]] - then - echo "[PROXYHOST] Failed to retrieve public ip address from AWS URI within 2s" - fi -fi - -## PUBLIC_IP retrieved from third-party sources -if [[ $PUBLIC_IP == '' ]] -then - urls=( - 'https://icanhazip.com/' - 'https://ipinfo.io/ip' - 'https://domains.google.com/checkip' - ) - - # Attempt retrieval of the public ip from the third-party sources - for url in "${urls[@]}"; do - PUBLIC_IP="$(fetch "${url}")" && break - done - if [[ $PUBLIC_IP == '' ]] - then - echo "[PROXYHOST] Failed to retrieve public ip address from third-party sources within 2s" - fi -fi - -# Now if the public IP is available (test is for not-empty) -# then replace the instances in all haproxy config lines -if [[ -n "$PUBLIC_IP" ]] -then - echo "[PROXYHOST] Public IP address ($PUBLIC_IP) in-place replacement occurring on $CONFIG_FILE" - # Replace all instances of #PUBLIC_IP with the - # haproxy configuration statement for the frontend which set's the destination - # ip to the public ip of the container (which is necessary to determine our IP's - # internally within WA) - sed -i "s/#PUBLIC\_IP/tcp-request connection set-dst ipv4($PUBLIC_IP)/g" $CONFIG_FILE -fi - -# Setup a new, on-the-fly certificate for the HTTPS port (so this re-generates each restart) -pushd /home/haproxy/certs -/usr/local/bin/generate-certs.sh -mv proxy.whatsapp.net.pem /etc/haproxy/ssl/proxy.whatsapp.net.pem -chown haproxy:haproxy /etc/haproxy/ssl/proxy.whatsapp.net.pem -popd - -# Start HAProxy -haproxy -f "$CONFIG_FILE" - diff --git a/proxy/src/start.sh b/proxy/src/start.sh new file mode 100755 index 00000000..30ad80b0 --- /dev/null +++ b/proxy/src/start.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# License found in the LICENSE file in the root directory +# of this source tree. + +set -e + +CONFIG_FILE="/usr/local/etc/haproxy/haproxy.cfg" + +# Generate a new certificate for the HTTPS port on each startup. +pushd /home/haproxy/certs +/usr/local/bin/generate-certs.sh +mv proxy.whatsapp.net.pem /etc/haproxy/ssl/proxy.whatsapp.net.pem +chown haproxy:haproxy /etc/haproxy/ssl/proxy.whatsapp.net.pem +popd + +# Start HAProxy as the container's main process. +exec haproxy -f "$CONFIG_FILE"