Mạng
Kiến trúc: Edge Ingress + API Gateway
BANA phân tách edge ingress khỏi API gateway. Điều này phản ánh cấu hình Docker Compose hiện tại, nơi Traefik chỉ xử lý định tuyến API backend.
Tại sao Hai Tầng
| Trách nhiệm | nginx-ingress (edge) | Traefik (API gateway) |
|---|---|---|
| Kết thúc TLS | Có | Không (nhận HTTP thuần) |
| Phục vụ file tĩnh | Định tuyến đến nginx pod | Không |
| Rate limiting API | Không | Có (theo từng route) |
| Circuit breaking | Không | Có (theo từng dịch vụ) |
| Security header | Không | Có (dành riêng cho API) |
| Middleware xác thực | Không | Có (dashboard-auth, rate-limit-auth) |
| Nâng cấp WebSocket | Chuyển tiếp | Xử lý route /stream |
| Chuyển đổi đường dẫn webhook | Không | Có (chuyển đổi đường dẫn payment webhook) |
nginx-ingress (Tầng Edge)
Deployment
Staging: 1 bản sao trên node default
# Staging: 1 bản sao trên node default
# Production: 2 bản sao trên node system (có taint)
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: nx-internal
spec:
replicas: 2 # Production; 1 cho staging
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
spec:
tolerations: # Chỉ Production
- key: dedicated
value: system
effect: NoSchedule
nodeSelector:
node.kubernetes.io/pool: system # Production: system; Staging: default
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.12.2
args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443Quy tắc Ingress
Frontend Ingress — định tuyến theo host đến ứng dụng frontend trong nx-app
# Frontend Ingress — định tuyến theo host đến ứng dụng frontend trong nx-app
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nx-frontend-ingress
namespace: nx-app
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
ingressClassName: nginx
tls:
- hosts:
- staging.bana.com.vn
- client.staging.bana.com.vn
- bo.staging.bana.com.vn
- sale.staging.bana.com.vn
- wiki.staging.bana.com.vn
secretName: staging-bana-tls
rules:
- host: staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-overture
port:
number: 80
- host: client.staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-client
port:
number: 80
- host: bo.staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-bo
port:
number: 80
- host: sale.staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-sale-renderer
port:
number: 80
- host: wiki.staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-wiki
port:
number: 80
---
# Backend Ingress — định tuyến lưu lượng API đến Traefik trong nx-internal
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nx-backend-ingress
namespace: nx-internal
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
ingressClassName: nginx
tls:
- hosts:
- sgw.staging.bana.com.vn
secretName: staging-bana-tls
rules:
- host: sgw.staging.bana.com.vn
http:
paths:
- path: /v1/api
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 80
- path: /stream
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 80
- path: /dashboard
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 8080
- path: /api
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 80
---
# Payment webhook — host riêng
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nx-webhook-ingress
namespace: nx-internal
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
ingressClassName: nginx
tls:
- hosts:
- hook.staging.bana.com.vn
secretName: staging-bana-tls
rules:
- host: hook.staging.bana.com.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nx-traefik
port:
number: 80cert-manager
Tự động quản lý chứng chỉ TLS qua Let's Encrypt.
ClusterIssuer: letsencrypt-prod
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: devops@nexpando.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginxTraefik API Gateway
Traefik chạy dưới dạng Deployment thông thường (không phải IngressController) trong namespace nx-internal. Nó nhận lưu lượng từ nginx-ingress và định tuyến đến các dịch vụ backend.
Deployment
Deployment: nx-traefik
apiVersion: apps/v1
kind: Deployment
metadata:
name: nx-traefik
namespace: nx-internal
spec:
replicas: 2 # Production; 1 cho staging
selector:
matchLabels:
app.kubernetes.io/name: traefik
template:
metadata:
labels:
app.kubernetes.io/name: traefik
spec:
nodeSelector:
node.kubernetes.io/pool: app # Staging: default
containers:
- name: traefik
image: traefik:v3.6
args:
- --api.dashboard=true
- --api.insecure=true
- --entrypoints.web.address=:8000
- --providers.file.directory=/etc/traefik/dynamic
- --providers.file.watch=true
- --metrics.prometheus=true
- --metrics.prometheus.addEntryPointsLabels=true
- --metrics.prometheus.addServicesLabels=true
- --accesslog=true
- --accesslog.format=json
- --tracing.otlp.grpc.endpoint=nx-otel-collector.nx-watcher.svc.cluster.local:4317
ports:
- name: web
containerPort: 8000
- name: dashboard
containerPort: 8080
volumeMounts:
- name: dynamic-config
mountPath: /etc/traefik/dynamic
volumes:
- name: dynamic-config
configMap:
name: traefik-dynamic-config
---
apiVersion: v1
kind: Service
metadata:
name: nx-traefik
namespace: nx-internal
spec:
selector:
app.kubernetes.io/name: traefik
ports:
- name: web
port: 80
targetPort: 8000
- name: dashboard
port: 8080
targetPort: 8080Cấu hình Động (File Provider)
Traefik sử dụng file provider (không phải Kubernetes CRD hay Docker label) cho cấu hình routing, được lưu trong ConfigMap:
ConfigMap: traefik-dynamic-config
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-dynamic-config
namespace: nx-internal
data:
services.yml: |
http:
routers:
identity:
rule: "PathPrefix(`/v1/api/identity`)"
service: identity
middlewares:
- rate-limit-auth
- circuit-breaker
- security-headers
commerce:
rule: "PathPrefix(`/v1/api/commerce`)"
service: commerce
middlewares:
- rate-limit
# TODO: re-enable circuit-breaker after S3 i18n.json fix
- security-headers
sale:
rule: "PathPrefix(`/v1/api/sale`)"
service: sale
middlewares:
- rate-limit
- circuit-breaker
- security-headers
finance:
rule: "PathPrefix(`/v1/api/finance`)"
service: finance
middlewares:
- rate-limit
- circuit-breaker
- security-headers
inventory:
rule: "PathPrefix(`/v1/api/inventory`)"
service: inventory
middlewares:
- rate-limit
- circuit-breaker
- security-headers
ledger:
rule: "PathPrefix(`/v1/api/ledger`)"
service: ledger
middlewares:
- rate-limit
- circuit-breaker
- security-headers
pricing:
rule: "PathPrefix(`/v1/api/pricing`)"
service: pricing
middlewares:
- rate-limit
- circuit-breaker
- security-headers
payment:
rule: "PathPrefix(`/v1/api/payment`)"
service: payment
middlewares:
- rate-limit
- circuit-breaker
- security-headers
payment-webhook:
rule: "Host(`hook.staging.bana.com.vn`)"
priority: 100
service: payment
middlewares:
- payment-add-prefix
- security-headers
signal-rest:
rule: "PathPrefix(`/v1/api/signal`)"
service: signal
middlewares:
- rate-limit
- circuit-breaker
- security-headers
signal-ws:
rule: "PathPrefix(`/stream`)"
service: signal
dashboard:
rule: "PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
service: api@internal
middlewares:
- dashboard-auth
services:
identity:
loadBalancer:
servers:
- url: "http://nx-identity.nx-backend.svc.cluster.local:3000"
healthCheck:
path: /v1/api/identity/health
interval: 30s
commerce:
loadBalancer:
servers:
- url: "http://nx-commerce.nx-backend.svc.cluster.local:3000"
healthCheck:
path: /v1/api/commerce/health
interval: 30s
sale:
loadBalancer:
servers:
- url: "http://nx-sale.nx-backend.svc.cluster.local:3000"
healthCheck:
path: /v1/api/sale/health
interval: 30s
finance:
loadBalancer:
servers:
- url: "http://nx-finance.nx-backend.svc.cluster.local:3000"
inventory:
loadBalancer:
servers:
- url: "http://nx-inventory.nx-backend.svc.cluster.local:3000"
ledger:
loadBalancer:
servers:
- url: "http://nx-ledger.nx-backend.svc.cluster.local:3000"
pricing:
loadBalancer:
servers:
- url: "http://nx-pricing.nx-backend.svc.cluster.local:3000"
payment:
loadBalancer:
servers:
- url: "http://nx-payment-api.nx-backend.svc.cluster.local:3000"
healthCheck:
path: /v1/api/payment/health
interval: 30s
signal:
loadBalancer:
servers:
- url: "http://nx-signal.nx-backend.svc.cluster.local:3000"
healthCheck:
path: /v1/api/signal/health
interval: 30s
middlewares.yml: |
http:
middlewares:
rate-limit:
rateLimit:
average: 200
burst: 400
period: 1s
sourceCriterion:
requestHeaderName: X-Real-Ip
rate-limit-auth:
rateLimit:
average: 30
burst: 60
period: 60s
sourceCriterion:
requestHeaderName: X-Real-Ip
circuit-breaker:
circuitBreaker:
expression: "ResponseCodeRatio(500, 600, 0, 600) > 0.30 || NetworkErrorRatio() > 0.10 || LatencyAtQuantileMS(95.0) > 3000"
checkPeriod: 10s
fallbackDuration: 15s
recoveryDuration: 30s
security-headers:
headers:
browserXssFilter: true
contentTypeNosniff: true
frameDeny: true
customResponseHeaders:
Server: ""
X-Powered-By: ""
dashboard-auth:
basicAuth:
users:
- "admin:$apr1$..."
payment-add-prefix:
replacePathRegex:
regex: "^/v1/api/(.*)"
replacement: "/v1/api/payment/$1"
## DNS
| Domain | Đích | Mục đích |
|--------|--------|---------|
| `sgw.staging.bana.com.vn` | Cloud LB → nginx-ingress | Backend API |
| `hook.staging.bana.com.vn` | Cloud LB → nginx-ingress → Traefik | Payment webhook |
| `staging.bana.com.vn` | Cloud LB → nginx-ingress | Overture (trang chủ) |
| `client.staging.bana.com.vn` | Cloud LB → nginx-ingress | Client SPA |
| `bo.staging.bana.com.vn` | Cloud LB → nginx-ingress | Back-office |
| `sale.staging.bana.com.vn` | Cloud LB → nginx-ingress | Sale renderer |
| `wiki.staging.bana.com.vn` | Cloud LB → nginx-ingress | Tài liệu |
## DNS Nội bộ (K8s Service)Dịch vụ backend (nx-backend)
nx-identity.nx-backend.svc.cluster.local:3000 nx-commerce.nx-backend.svc.cluster.local:3000 nx-sale.nx-backend.svc.cluster.local:3000 nx-signal.nx-backend.svc.cluster.local:3000 ...
Dịch vụ frontend (nx-app)
nx-client.nx-app.svc.cluster.local:80 nx-bo.nx-app.svc.cluster.local:80 ...
PostgreSQL qua PgBouncer (nx-persistent)
nx-pgbouncer.nx-persistent.svc.cluster.local:5432
Redis cluster & Kafka (nx-broker)
nx-redis-{0,1,2}.nx-redis-headless.nx-broker.svc.cluster.local:6379 nx-kafka-{0,1,2}.nx-kafka-headless.nx-broker.svc.cluster.local:9092
Typesense (nx-search)
nx-typesense.nx-search.svc.cluster.local:8108
API Gateway (nx-internal)
nx-traefik.nx-internal.svc.cluster.local:80
## Network Policy
### Tổng Quan Luồng Lưu Lượng
Tất cả namespace bắt đầu với **default-deny** (ingress + egress). Lưu lượng sau đó được cho phép rõ ràng. Các sơ đồ dưới đây trực quan hóa mọi đường dẫn được phép.
#### Luồng Ingress (ai có thể gửi lưu lượng đến đâu)
```mermaid
graph LR
Internet((Internet))
subgraph "nx-internal"
Nginx[nginx-ingress]
Traefik[Traefik]
Portal[API Portal]
end
subgraph "nx-backend"
BE[Backend Services<br/>identity, commerce, sale,<br/>finance, inventory, ledger,<br/>pricing, signal, payment]
end
subgraph "nx-app"
FE[Frontend Apps<br/>client, bo, overture,<br/>sale-renderer, wiki]
end
subgraph "nx-persistent"
PGB[PgBouncer :5432]
PG_P[PG Primary :5432]
PG_R[PG Replica :5432]
end
subgraph "nx-broker"
Redis[Redis Cluster<br/>:6379 :16379]
Kafka[Kafka Brokers<br/>:9092 :29092 :9093]
end
subgraph "nx-search"
TS[Typesense :8108]
DBZ[Debezium :8083]
end
Internet -->|":80/:443"| Nginx
Nginx -->|":8000/:8080"| Traefik
Traefik -->|":80"| Portal
Nginx -->|":3000/:8000"| BE
Nginx -->|":80"| FE
BE -->|":5432"| PGB
PGB -->|":5432"| PG_P
PG_P -->|"WAL :5432"| PG_R
BE -->|":6379/:16379"| Redis
BE -->|":9092"| Kafka
BE -->|":8108"| TS
BE -->|":3000 inter-svc"| BE
classDef denied fill:#fee,stroke:#f66,stroke-dasharray: 5 5
classDef ns fill:#f0f8ff,stroke:#4a86c8Luồng Egress (ai có thể truy cập bên ngoài cluster)
Ma Trận Giao Tiếp Giữa Các Namespace
Chính sách Default-Deny
Mỗi namespace bắt đầu với chính sách default-deny cho cả ingress và egress. Lưu lượng sau đó được cho phép rõ ràng qua các chính sách bổ sung.
Default deny tất cả ingress và egress cho nx-backend
# Default deny tất cả ingress và egress cho nx-backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nx-backend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Default deny tất cả cho nx-app
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nx-app
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Default deny tất cả cho nx-persistent
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nx-persistent
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Default deny tất cả cho nx-broker
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nx-broker
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Default deny tất cả cho nx-search
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nx-search
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressWARNING
Chính sách default-deny chặn tất cả lưu lượng bao gồm DNS. Mỗi namespace cũng cần quy tắc egress cho phép phân giải DNS (port 53 đến kube-system).
Cho phép phân giải DNS cho tất cả pod trong namespace
# Cho phép phân giải DNS cho tất cả pod trong namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: nx-backend
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Lặp lại chính sách cho phép DNS cho mỗi namespace có default-deny.
Chính sách Ingress Cho phép
Cho phép nx-internal (nginx-ingress) → nx-backend + nx-app
# Cho phép nx-internal (nginx-ingress) → nx-backend + nx-app
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-backend
namespace: nx-backend
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-internal
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-app
namespace: nx-app
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-internal
---
# Cho phép nx-backend → nx-persistent, nx-broker, nx-search
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-persistent
namespace: nx-persistent
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-backend
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-broker
namespace: nx-broker
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-backend
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-search
namespace: nx-search
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-backend
---
# Cho phép nx-watcher → tất cả namespace (thu thập metrics)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring-scrape
namespace: nx-backend
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-watcher
ports:
- port: 3000 # metrics endpointChính sách Egress
Pod backend chỉ được truy cập namespace dữ liệu — không truy cập internet (ngoại trừ payment-api cho webhook).
nx-backend → chỉ namespace dữ liệu
# nx-backend → chỉ namespace dữ liệu
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress-to-data
namespace: nx-backend
spec:
podSelector: {}
policyTypes:
- Egress
egress:
# Cho phép truy cập namespace dữ liệu
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-persistent
ports:
- port: 5432
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-broker
ports:
- port: 6379 # Redis
- port: 16379 # Redis cluster bus
- port: 9092 # Kafka (CLIENT listener)
- port: 29092 # Kafka (CONTROLLER listener)
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-search
ports:
- port: 8108 # Typesense
# Cho phép giao tiếp nội bộ (trong nx-backend)
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-backend
ports:
- port: 3000
- port: 8000 # Traefik
---
# payment-api — cho phép thêm truy cập internet cho webhook callback
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: payment-egress-internet
namespace: nx-backend
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: payment-api
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- port: 443
protocol: TCP
---
# identity — cho phép thêm truy cập internet cho nhà cung cấp SMS/email
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-identity-internet
namespace: nx-backend
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: identity
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- port: 443
protocol: TCP
---
# Dịch vụ backend — cho phép truy cập S3-compatible object storage
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-to-s3
namespace: nx-backend
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- port: 443
protocol: TCP
---
# Cho phép nginx-ingress → Traefik trong nx-internal
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traefik-from-nginx
namespace: nx-internal
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: traefik
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- port: 8000
- port: 8080
---
# Cho phép Traefik → api-portal trong nx-internal
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-portal-from-traefik
namespace: nx-internal
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: api-portal
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: traefik
ports:
- port: 3000
---
# Cho phép lưu lượng nội bộ trong nx-search (cho Debezium connector)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-search-internal
namespace: nx-search
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nx-searchMa trận Network Policy
| Namespace Nguồn | Đích | Port | Hướng |
|---|---|---|---|
nx-internal | nx-backend, nx-app | 3000, 8000, 80 | Ingress |
nx-internal (nginx) | nx-internal (traefik) | 8000, 8080 | Ingress |
nx-internal (traefik) | nx-internal (api-portal) | 3000 | Ingress |
nx-backend | nx-persistent | 5432 | Egress |
nx-backend | nx-broker | 6379, 16379, 9092, 29092 | Egress |
nx-backend | nx-search | 8108 | Egress |
nx-backend | nx-backend (nội bộ) | 3000, 8000 | Egress |
nx-backend (chỉ payment-api) | Internet | 443 | Egress |
nx-backend (chỉ identity) | Internet | 443 | Egress |
nx-backend | S3 (Internet) | 443 | Egress |
nx-search | nx-search (nội bộ) | tất cả | Ingress |
nx-watcher | Tất cả | port metrics | Ingress |
| Tất cả | kube-system | 53 (DNS) | Egress |