How-To: Scanning Internal Applications via Envoy Forward Proxy
Last updated: June 1, 2026
Introduction
When internal applications, APIs, or IPs are not publicly accessible, exposing each service to the internet is often not feasible. Deployment of an Envoy forward proxy within the private network allows Astra to route scanning traffic through it to reach internal applications without exposing them publicly.
The setup uses a forward proxy VM inside the private network. Astra, which has a fixed set of scanning IPs, sends HTTP and port scan requests to the client infrastructure through the Envoy proxy. The proxy enforces access controls and logging, while allowing centralized management of inbound scanning traffic.
Astra Scanner (Fixed IPs) → Envoy Proxy → Internal Applications / APIs / IPs
Prerequisites
A Virtual Machine (VM) provisioned within the private network that has access to all internal applications to be scanned.
The VM must be reachable from Astra’s fixed scanning IP ranges.
Proper administrative permissions to configure firewall rules and deploy software on the proxy host.
Instructions
Step 1. Deploy Envoy Proxy VM
Provision a host within your internal infrastructure that can communicate with the restricted target applications.
Step 2. Configure HTTP Dynamic Forward Proxy:
Set up Envoy with dynamic forward proxy functionality to handle request routing.
Step 3. Implement Access Controls:
Apply RBAC rules to restrict incoming requests to Astra's static IPs only and enable access logging for auditability.
Reference Guides:
Step 4. Firewall and Security
Configure firewall rules to allow traffic from Astra’s scanning IPs only.
Limit outbound access from the proxy to only the internal applications required for scanning.
Optionally, enforce authorization headers for added security.
Step 5. Deployment options
Use the provided Ansible playbook below to automate prerequisites installation and Envoy configuration on a VM, or use the Kubernetes manifests (ConfigMap, Deployment, and Service) for containerized environments.
Note: This playbook provides a basic installation and configuration of Envoy as a forward proxy. You are encouraged to extend it further by adding RBAC policies, access controls, logging, monitoring, and TLS/mTLS configurations as per your organizational security and compliance requirements.
---
- name: Install and configure Envoy as forward proxy
hosts: all
become: yes
gather_facts: false
vars:
envoy_config_file: /etc/envoy/envoy.yaml
envoy_proxy_port: 8080
envoy_admin_port: 9901
envoy_distro: "{{ ansible_distribution_release }}" # e.g., 'focal' for Ubuntu 20.04, 'jammy' for Ubuntu 22.04, 'noble' for 24.04
tasks:
- name: Ensure prerequisites are installed
apt:
name:
- wget
- gpg
- ca-certificates
- apt-transport-https # For HTTPS repo support
state: present
update_cache: yes
- name: Add Envoy signing key
shell: |
wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/envoy-keyring.gpg
args:
creates: /etc/apt/trusted.gpg.d/envoy-keyring.gpg
- name: Add Envoy apt repository
copy:
content: "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/envoy-keyring.gpg] https://apt.envoyproxy.io {{ envoy_distro }} main"
dest: /etc/apt/sources.list.d/envoy.list
notify: Update apt cache
- name: Update apt cache
apt:
update_cache: yes
changed_when: false
- name: Install Envoy
apt:
name: envoy
state: present
- name: Create Envoy configuration directory
file:
path: /etc/envoy
state: directory
mode: '0755'
- name: Deploy Envoy forward proxy configuration
copy:
content: |
admin:
address:
socket_address:
address: 0.0.0.0
port_value: {{ envoy_admin_port }}
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: {{ envoy_proxy_port }}
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
http_filters:
- name: envoy.filters.http.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
# Existing route for regular HTTP requests (absolute URIs)
- match:
prefix: "/"
route:
cluster: dynamic_forward_proxy_cluster
# New route for HTTPS (CONNECT) requests - this fixes the 404
- match:
connect_matcher: {}
route:
cluster: dynamic_forward_proxy_cluster
upgrade_configs:
- upgrade_type: CONNECT
connect_config: {}
clusters:
- name: dynamic_forward_proxy_cluster
lb_policy: CLUSTER_PROVIDED
cluster_type:
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
dest: "{{ envoy_config_file }}"
notify: Restart Envoy
- name: Create Envoy systemd service
copy:
content: |
[Unit]
Description=Envoy Proxy
After=network.target
[Service]
ExecStart=/usr/bin/envoy -c {{ envoy_config_file }}
Restart=always
User=root
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/envoy.service
notify: Reload systemd
- name: Reload systemd daemon
systemd:
daemon_reload: yes
- name: Enable and start Envoy service
service:
name: envoy
enabled: yes
state: started
handlers:
- name: Update apt cache
apt:
update_cache: yes
- name: Restart Envoy
service:
name: envoy
state: restarted
- name: Reload systemd
systemd:
daemon_reload: yesKubernetes Deployment
ConfigMap
apiVersion: v1
data:
envoy_config.yaml: |-
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
http_filters:
- name: envoy.filters.http.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
# Existing route for regular HTTP requests (absolute URIs)
- match:
prefix: "/"
route:
cluster: dynamic_forward_proxy_cluster
# New route for HTTPS (CONNECT) requests - this fixes the 404
- match:
connect_matcher: {}
route:
cluster: dynamic_forward_proxy_cluster
upgrade_configs:
- upgrade_type: CONNECT
connect_config: {}
clusters:
- name: dynamic_forward_proxy_cluster
lb_policy: CLUSTER_PROVIDED
cluster_type:
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
kind: ConfigMap
metadata:
name: envoy-configDeployment
kind: Deployment
apiVersion: apps/v1
metadata:
name: envoy-gateway
spec:
replicas: 2
selector:
matchLabels:
app: envoy
template:
metadata:
labels:
app: envoy
spec:
restartPolicy: Always
securityContext: {}
containers:
- resources:
limits:
cpu: 150m
memory: 1Gi
requests:
cpu: 100m
memory: 256Mi
readinessProbe:
httpGet:
path: /ready
port: admin-http
scheme: HTTP
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
name: envoy-gateway
livenessProbe:
httpGet:
path: /ready
port: admin-http
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 1
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
securityContext:
capabilities:
drop:
- ALL
privileged: false
runAsGroup: 65532
runAsUser: 65532
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: admin-http
containerPort: 9901
protocol: TCP
imagePullPolicy: IfNotPresent
volumeMounts:
- name: envoy-gateway-config
readOnly: true
mountPath: /config
image: envoyproxy/envoy:v1.35.3
args: ["-c", "/config/envoy_config.yaml"]
volumes:
- name: envoy-gateway-config
configMap:
name: envoy-config
defaultMode: 420
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10Service
apiVersion: v1
kind: Service
metadata:
name: envoy-proxy
namespace: default
spec:
type: ClusterIP
ports:
- name: http
port: 8080
targetPort: http
- name: admin-http
port: 9901
targetPort: admin-http
selector:
app: envoyOverall Process
Review the Setup: Discuss requirements and specific configurations with the Astra Engineering team.
Deploy the Forward Proxy: Follow the guidelines to set up the Envoy instance in your internal network.
Provide Connection Details: Share the proxy's connection information, including IP, port, and credentials (if applicable), with Astra.
Configuration & Testing: Astra will configure the scanners to utilize the proxy and perform a test connection to verify that internal applications are reachable.
Expected Outcome
Astra will be able to perform a secure, non-intrusive security assessment of your private internal assets. All scanning traffic is centralized through the proxy, providing a secure and auditable path for reachability.
Limitations & Best Practices
Protocol Restrictions: This setup generally only supports HTTP/HTTPS; non-HTTP services cannot be accessed through the proxy.
Port Scanning: Full network or port scans may not work as expected, as proxies typically only allow traffic on specific ports like 80 or 443.
Performance: Large scans may experience latency since all traffic is routed through a single proxy instance.
Access Control: Ensure RBAC and firewall rules are strictly configured to prevent unauthorized exposure of internal apps.
NOTE:This setup allows Astra to scan internal applications securely without exposing them publicly. Multiple internal apps can be accessed through a single proxy instance.Logging and RBAC provide visibility and security compliance.