Skip to main content
CID222 Docs

FortiProxy and FortiGate

Configure an on-premises FortiProxy or FortiGate explicit web proxy to send AI-bound traffic to CID222 over ICAP, scoped to the provider hostnames only.

  • Version: 0.4
  • Feature: icap
  • Role: admin_user
  • Type: task

FortiProxy already decrypts outbound sessions with the Fortinet certificate authority your endpoints trust. This procedure adds CID222 as an inspection service, scopes it to the provider hostnames so nothing else is decrypted, and proves that both a prompt and an image upload are redacted before they leave the network.

What do I need?

Licence
Any
Role
admin_user

Prerequisites

  • FortiProxy 7.2 or 7.4, or a FortiGate of the same generation running the explicit web proxy. FortiSASE customers use the FortiSASE page instead.
  • Administrative access to both the FortiProxy console and its command line.
  • Deep inspection already working for the traffic you intend to scope, which means the Fortinet certificate authority is already trusted on the endpoints.
  • The CID222 ICAP listener published and reachable from FortiProxy on TCP 1344 — see ICAP and third-party gateways.
  • FortiProxy's source address admitted by the appliance's peer list.

Note

This is the one integration validated end to end in the laboratory: FortiProxy 7.4.13 with the explicit web proxy, deep inspection and the ICAP client, against a CID222 appliance on 1344. Text-prompt masking and image-upload redaction are both confirmed. An acceptance test plan exists; several of its phases — Claude and Gemini coverage, latency under load, and the fail policy — are recorded as untested.

Configure FortiProxy

Several of these settings exist only on the command line, and one of them is the single most common reason an otherwise correct configuration inspects nothing.

Enable the explicit web proxy

On the client-facing interface, enable the explicit web proxy:

config system interface
    edit "port1"
        set explicit-web-proxy enable
    next
end

A client can now reach the proxy: curl -x http://<fortiproxy>:8080 http://example.com returns a normal response.

Reveal the ICAP feature

The console hides ICAP until it is switched on:

config system settings
    set gui-icap enable
end

A Content Analyses menu appears in the navigation, holding ICAP Remote Server and ICAP Profile.

Add CID222 as an ICAP remote server

Under Content Analyses → ICAP Remote Server, create a server named cid222 with the appliance address, port 1344, up to 1024 connections, and secure transport off — the listener has no encryption of its own and belongs on a trusted segment.

execute telnet <appliance-ip> 1344 from the FortiProxy command line connects.

Create the ICAP profile

Under Content Analyses → ICAP Profile, create cid222-icap with request processing enabled against the cid222 server, response processing left off, and streaming-content bypass disabled.

The profile appears in the list and can be attached to a policy. Two settings decide whether uploads are seen at all: the method set applies to request and response processing alike, so it must include both the method used by conversations and the method used by uploads; and streaming-content bypass, if enabled, lets large uploads skip inspection entirely.

Group the provider hostnames

Create fully-qualified-name address objects for the provider hostnames and collect them in one group. Include the upload hosts, not only the conversation hosts:

config firewall address
    edit "ai-chatgpt"        set type fqdn  set fqdn "chatgpt.com"                next
    edit "ai-openai"         set type fqdn  set fqdn "chat.openai.com"            next
    edit "ai-openai-cdn"     set type fqdn  set fqdn "*.oaiusercontent.com"       next
    edit "ai-claude"         set type fqdn  set fqdn "claude.ai"                  next
    edit "ai-gemini"         set type fqdn  set fqdn "gemini.google.com"          next
    edit "ai-gemini-upl"     set type fqdn  set fqdn "push.clients6.google.com"   next
    edit "ai-aistudio"       set type fqdn  set fqdn "aistudio.google.com"        next
    edit "ai-google-content" set type fqdn  set fqdn "content.googleapis.com"     next
end

The group lists every host you expect to inspect. Missing *.oaiusercontent.com or content.googleapis.com costs you image redaction on ChatGPT and on AI Studio respectively, with no error anywhere.

Clone the deep-inspection profile and remove the Google exemption

The stock deep-inspection profile is read-only and its exemption list contains a wildcard for googleapis.com. While that exemption is active, FortiProxy does not decrypt content.googleapis.com, so no plaintext is produced, no inspection is requested, and AI Studio uploads leave the network unread.

config firewall ssl-ssh-profile
    clone deep-inspection to cid222-deep-inspection
    edit cid222-deep-inspection
        config ssl-exempt
            show
            delete <id-of-the-googleapis-entry>
        end
    next
end

show firewall ssl-ssh-profile cid222-deep-inspection | grep -A1 ssl-exempt | grep -i google prints nothing. Remove only the entry that overlaps your group; the other stock exemptions exist because breaking those services breaks unrelated software.

Point the AI policy at the clone

Edit the policy that carries the provider hostnames so its destination is the address group, its inspection profile is the clone, and its ICAP profile is cid222-icap.

config firewall proxy-policy
    edit <policy-id>
        set dstaddr "ai-websites"
        set ssl-ssh-profile "cid222-deep-inspection"
        set icap-profile "cid222-icap"
        set utm-status enable
    next
end

The policy list shows the new destination and profiles.

Add a catch-all below it

Add a policy for everything else that accepts with certificate inspection only — no decryption and no ICAP profile — and confirm it sits below the AI policy, because matching is first-match-wins.

show firewall proxy-policy lists the AI policy first. Reorder with move <ai-id> before <catchall-id> if it does not.

Verify

  1. From a workstation behind the proxy, send a prompt containing a test identifier to ChatGPT. The model receives the value masked, and CID222 records MESSAGE_MASKED.
  2. Upload an image of an identity document and ask the model to read the number. The model reports the fields as blacked out; CID222 records FILE_UPLOAD_REDACTED for a *.oaiusercontent.com host. What the model says is the evidence — the browser thumbnail is always your local original.
  3. Send a prompt with no personal data. It is forwarded unchanged and no block appears.
  4. Browse to a site outside the group — a bank, a news site. The certificate the browser reports is the real one, not Fortinet's, proving that site is not decrypted.
  5. On Detection & Filtering → Browser Inspection, FortiProxy appears in the connected-sources table with a recent timestamp.

If it fails

  • execute telnet cannot reach 1344 → the listener is not published, a firewall is in the way, or the appliance's peer list does not admit FortiProxy's address.
  • A host you added to the group produces no inspection traffic at all → it overlaps an entry in the inspection profile's exemption list. This is the most common cause, and the browser keeps working, so it looks like the policy is not applying when in fact the exemption overrides it.
  • Errors appear for provider hosts only, for about ten seconds after a CID222 restart → expected; the connection pool holds stale sockets until they cycle. Set the profile's on-failure behaviour to bypass if that blip must be invisible.
  • Text is redacted but images are not → the upload host is missing from the group, the profile's method set excludes the upload method, or streaming-content bypass is enabled.
  • Non-AI sites show the Fortinet certificate → the catch-all policy is missing, sits above the AI policy, or uses the deep-inspection profile.
  • The peer list appears to have no effect in a laboratory where FortiProxy is a virtual machine on the appliance host → Every ICAP caller arrives as the same docker bridge address.

Known limits on this path

  • Uploads in the WEBP image format are blocked rather than redacted. Redaction re-encodes the image larger than the original, the upload's declared size no longer matches, and CID222 refuses rather than sending bytes the provider will reject. JPEG and PNG are unaffected.
  • Fragmented uploads are refused. Google's resumable upload protocol splits one file across many requests; a fragment cannot be inspected alone, so it is blocked and the user sees a failed upload.
  • Response-side inspection is noisier than request-side. Leave it off for a first deployment.
  • Mobile applications that pin certificates, unmanaged devices, HTTP/3 and on-device models are outside any network-layer control. See Interception topologies.

Next steps

Last updated on

On this page

Download PDF