Internet-Draft | Secure ICAP BCP | June 2025 |
Cameron | Expires 28 December 2025 | [Page] |
This document defines a Best Current Practice for deploying the Internet Content Adaptation Protocol (ICAP) in a secure manner. It introduces a mechanism for symmetric encryption using TLS, with client authentication based on user credentials. The aim is to provide confidentiality and integrity of ICAP traffic in modern zero-trust and content-sensitive environments.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 28 December 2025.¶
Copyright (c) 2025 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
ICAP [RFC3507] provides offloading of content adaptation to dedicated servers but lacks native support for transport-layer security and authentication. This document offers operational guidance for deploying ICAP securely using TLS with short-lived credential-based sessions to enable multi-tenant ICAP services.¶
This BCP is intended for ICAP implementers and administrators deploying ICAP within security-sensitive environments where plaintext transport and persistent sessions are undesirable. This is particularly applicable to public ICAP services serving multiple customers.¶
Clients MUST authenticate using a username/password mechanism encoded via HTTP Basic Authorization header. This credential pair MUST be used to derive a 256-bit session key using PBKDF2 with SHA-256.¶
The derived session key serves as an additional authentication layer beyond TLS transport security, enabling multi-tenant session isolation and per-customer access control within the ICAP service.¶
ICAP servers MUST accept connections only over TLS 1.2 or newer. The recommended port for secure ICAP ("ICAPS") is 11344. Non-encrypted connections SHOULD be rejected by default.¶
Session keys and associated TLS sessions MUST expire no later than one (1) hour after creation. Clients SHOULD re-authenticate upon session renewal.¶
Implementations MUST include the Authorization header during the initial handshake. TLS renegotiation SHOULD NOT be used. Session rekeying MUST be triggered by explicit re-authentication.¶
No new IANA actions are required by this document.¶
C: CONNECT icap.example.com:11344 S: <TLS Handshake> C: Authorization: Basic <base64-encoded credentials> ... <ICAP request begins within TLS session>¶
function connectToSecureICAPServer(username, password): tlsSocket = TLS.connect("icap.example.com", 11344, verifyCertificates=True) credentials = base64Encode(username + ":" + password) authHeader = "Authorization: Basic " + credentials // Prepare ICAP OPTIONS request request = ICAPRequest() request.method = "OPTIONS" request.uri = "icap://icap.example.com/reqmod" request.headers["Authorization"] = authHeader tlsSocket.send(request.serialize()) response = tlsSocket.receive() if response.statusCode == 200: print("Secure session established.") startSessionTimeout(1 hour) else if response.statusCode == 407: print("Authentication failed.") tlsSocket.close()¶
function handleSecureICAPConnection(tlsSocket): request = parseICAPRequest(tlsSocket.receive()) if not isValidTLS(tlsSocket): tlsSocket.send(ICAPErrorResponse(403)) return if "Authorization" not in request.headers: tlsSocket.send(ICAPAuthChallenge(407)) return credentials = parseBasicAuth(request.headers["Authorization"]) if not validateUser(credentials.username, credentials.password): tlsSocket.send(ICAPAuthChallenge(407)) return sessionKey = deriveKeyPBKDF2( password=credentials.password, salt=generateServerSalt(), iterations=100000, keyLength=256 ) // Mark session valid for 1 hour based on session key createSecureSession(sessionKey, ttl=1 hour) tlsSocket.send(ICAPSuccessResponse(200))¶