Classic DMZ Architecture
Two firewalls separate the untrusted internet, the DMZ, and the internal network.
flowchart LR
subgraph INET["Internet (untrusted)"]
direction TB
clients["Untrusted clients,
scanners, attackers"]:::inetNode end fw1{{"Edge firewall
permits 80, 443, 25, 53
inbound to specific DMZ hosts"}}:::fwNode subgraph DMZ["DMZ (semi-trusted)"] direction TB proxy["Web reverse proxy"]:::dmzNode dns["Public DNS"]:::dmzNode smtp["SMTP relay"]:::dmzNode end fw2{{"Inner firewall
DMZ to specific internal
endpoints and ports only;
no internal-initiated traffic to DMZ"}}:::fwNode subgraph INTERNAL["Internal network (trusted)"] direction TB app["Application servers"]:::intNode db["Database"]:::intNode dc["Domain controller"]:::intNode files["File servers"]:::intNode end %% legitimate flows (solid blue) clients -->|"HTTP / HTTPS"| fw1 fw1 ==> proxy proxy -->|"app port only"| fw2 fw2 ==> app app -.->|"users egress to internet"| fw1 %% blocked attacker pivot (red dashed) proxy -. "pivot attempt — blocked by deny-by-default" .-> fw2 classDef inetNode fill:#eceff1,stroke:#455a64,stroke-width:1.5px,color:#263238,font-size:14px classDef dmzNode fill:#cfd8dc,stroke:#455a64,stroke-width:1.5px,color:#1a2327,font-size:14px classDef intNode fill:#e3f0fb,stroke:#1565c0,stroke-width:1.5px,color:#0d2c54,font-size:14px classDef fwNode fill:#fff3d6,stroke:#ffa000,stroke-width:2px,color:#5a3d00,font-size:13px style INET fill:#f5f6f7,stroke:#90a4ae,stroke-width:2px,color:#455a64 style DMZ fill:#eceff1,stroke:#455a64,stroke-width:3px,color:#455a64 style INTERNAL fill:#f3f8fe,stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 0 stroke:#1565c0,stroke-width:2.5px,color:#1565c0 linkStyle 1 stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 2 stroke:#1565c0,stroke-width:2.5px,color:#1565c0 linkStyle 3 stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 4 stroke:#1565c0,stroke-width:2px,color:#1565c0 linkStyle 5 stroke:#d84315,stroke-width:2.5px,color:#d84315
scanners, attackers"]:::inetNode end fw1{{"Edge firewall
permits 80, 443, 25, 53
inbound to specific DMZ hosts"}}:::fwNode subgraph DMZ["DMZ (semi-trusted)"] direction TB proxy["Web reverse proxy"]:::dmzNode dns["Public DNS"]:::dmzNode smtp["SMTP relay"]:::dmzNode end fw2{{"Inner firewall
DMZ to specific internal
endpoints and ports only;
no internal-initiated traffic to DMZ"}}:::fwNode subgraph INTERNAL["Internal network (trusted)"] direction TB app["Application servers"]:::intNode db["Database"]:::intNode dc["Domain controller"]:::intNode files["File servers"]:::intNode end %% legitimate flows (solid blue) clients -->|"HTTP / HTTPS"| fw1 fw1 ==> proxy proxy -->|"app port only"| fw2 fw2 ==> app app -.->|"users egress to internet"| fw1 %% blocked attacker pivot (red dashed) proxy -. "pivot attempt — blocked by deny-by-default" .-> fw2 classDef inetNode fill:#eceff1,stroke:#455a64,stroke-width:1.5px,color:#263238,font-size:14px classDef dmzNode fill:#cfd8dc,stroke:#455a64,stroke-width:1.5px,color:#1a2327,font-size:14px classDef intNode fill:#e3f0fb,stroke:#1565c0,stroke-width:1.5px,color:#0d2c54,font-size:14px classDef fwNode fill:#fff3d6,stroke:#ffa000,stroke-width:2px,color:#5a3d00,font-size:13px style INET fill:#f5f6f7,stroke:#90a4ae,stroke-width:2px,color:#455a64 style DMZ fill:#eceff1,stroke:#455a64,stroke-width:3px,color:#455a64 style INTERNAL fill:#f3f8fe,stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 0 stroke:#1565c0,stroke-width:2.5px,color:#1565c0 linkStyle 1 stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 2 stroke:#1565c0,stroke-width:2.5px,color:#1565c0 linkStyle 3 stroke:#1565c0,stroke-width:3px,color:#1565c0 linkStyle 4 stroke:#1565c0,stroke-width:2px,color:#1565c0 linkStyle 5 stroke:#d84315,stroke-width:2.5px,color:#d84315
Legitimate flow (allowed)
Internal users egress to internet
Attacker pivot — blocked
DMZ (slate)
Internal (trusted)
Firewall