From: Christos Tsantilas Date: Fri, 24 Feb 2012 13:17:24 +0000 (+0200) Subject: Merge from trunk X-Git-Tag: BumpSslServerFirst.take05~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03f00a1184594d82540b50b4c6ba3568993f1cb7;p=thirdparty%2Fsquid.git Merge from trunk --- 03f00a1184594d82540b50b4c6ba3568993f1cb7 diff --cc src/cache_cf.cc index ea38819c28,509ff91420..bea414f43d --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@@ -195,18 -195,10 +196,16 @@@ static void dump_http_port_list(StoreEn static void free_http_port_list(http_port_list **); #if USE_SSL - static void parse_https_port_list(https_port_list **); - static void dump_https_port_list(StoreEntry *, const char *, const https_port_list *); - static void free_https_port_list(https_port_list **); + #define parse_https_port_list(l) parsePortList((l),"https") + #define dump_https_port_list(e,n,l) dump_http_port_list((e),(n),(l)) + #define free_https_port_list(l) free_http_port_list((l)) + #define check_null_https_port_list(l) check_null_http_port_list((l)) +static void parse_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign); +static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslproxy_cert_sign *cert_sign); +static void free_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign); +static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt); +static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslproxy_cert_adapt *cert_adapt); +static void free_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt); - #if 0 - static int check_null_https_port_list(const https_port_list *); - #endif #endif /* USE_SSL */ static void parse_b_size_t(size_t * var); @@@ -910,10 -897,10 +906,10 @@@ configDoConfigure(void http_port_list *s; for (s = Config.Sockaddr.http; s != NULL; s = (http_port_list *) s->next) { - if (!s->cert && !s->key) + if (!s->cert) continue; - debugs(3, 1, "Initializing http_port " << s->http.s << " SSL context"); + debugs(3, 1, "Initializing http_port " << s->s << " SSL context"); s->staticSslContext.reset( sslCreateServerContext(s->cert, s->key, @@@ -922,12 -909,6 +918,12 @@@ s->sslContextSessionId)); Ssl::readCertChainAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->certsToChain, s->cert, s->key); + + if (!s->signPkey) - debugs(3, DBG_IMPORTANT, "No SSL private key configured for http_port " << s->http.s); ++ debugs(3, DBG_IMPORTANT, "No SSL private key configured for http_port " << s->s); + + Ssl::generateUntrustedCert(s->untrustedSigningCert, s->untrustedSignPkey, + s->signingCert, s->signPkey); } } @@@ -943,15 -924,6 +939,15 @@@ s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath, s->crlfile, s->dhfile, s->sslContextSessionId)); + + if (s->cert && s->sslBump) { + Ssl::readCertChainAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->certsToChain, s->cert, s->key); + if (!s->signPkey) - debugs(3, DBG_IMPORTANT, "No SSL private key configured for https_port " << s->http.s); ++ debugs(3, DBG_IMPORTANT, "No SSL private key configured for https_port " << s->s); + + Ssl::generateUntrustedCert(s->untrustedSigningCert, s->untrustedSignPkey, + s->signingCert, s->signPkey); + } } } @@@ -3899,6 -3865,6 +3889,21 @@@ parsePortList(http_port_list ** head, c parse_http_port_option(s, token); } ++#if USE_SSL ++ if (strcasecmp(protocol, "https") == 0) { ++ /* ssl-bump on https_port configuration requires either tproxy or intercepted, and vice versa */ ++ const bool hijacked = s->spoof_client_ip || s->intercepted; ++ if (s->sslBump && !hijacked) { ++ debugs(3, DBG_CRITICAL, "FATAL: ssl-bump on https_port requires tproxy/intercepted which is missing."); ++ self_destruct(); ++ } ++ if (hijacked && !s->sslBump) { ++ debugs(3, DBG_CRITICAL, "FATAL: tproxy/intercepted on https_port requires ssl-bump which is missing."); ++ self_destruct(); ++ } ++ } ++#endif ++ if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && s->s.IsAnyAddr()) { // clone the port options from *s to *(s->next) s->next = clone_http_port_list(s); diff --cc src/cf.data.pre index 67409e0fe1,d432309843..0dde521835 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@@ -1530,114 -1526,7 +1557,115 @@@ DOC_STAR You may specify multiple socket addresses on multiple lines, each with their own SSL certificate and/or options. + Modes: + + accel Accelerator / reverse proxy mode + + tproxy Support Linux TPROXY for spoofing outgoing + connections using the client IP address. + NP: disables authentication and maybe IPv6 on the port. + + ssl-bump Intercept each SSL request matching ssl_bump ACL, + establish secure connection with the client and with + the server, decrypt HTTP messages as they pass through + Squid, and treat them as unencrypted HTTP messages, + becoming the man-in-the-middle. + + The ssl_bump option is required to fully enable + the SslBump feature. + + Requires tproxy. + + Omitting the mode flag causes default forward proxy mode to be used. + + + See http_port for a list of generic options + + + SSL Options: + + cert= Path to SSL certificate (PEM format). + + key= Path to SSL private key file (PEM format) + if not specified, the certificate file is + assumed to be a combined certificate and + key file. + + version= The version of SSL/TLS supported + 1 automatic (default) + 2 SSLv2 only + 3 SSLv3 only + 4 TLSv1 only + + cipher= Colon separated list of supported ciphers. + + options= Various SSL engine options. The most important + being: + NO_SSLv2 Disallow the use of SSLv2 + NO_SSLv3 Disallow the use of SSLv3 + NO_TLSv1 Disallow the use of TLSv1 + SINGLE_DH_USE Always create a new key when using + temporary/ephemeral DH key exchanges + See src/ssl_support.c or OpenSSL SSL_CTX_set_options + documentation for a complete list of options. + + clientca= File containing the list of CAs to use when + requesting a client certificate. + + cafile= File containing additional CA certificates to + use when verifying client certificates. If unset + clientca will be used. + + capath= Directory containing additional CA certificates + and CRL lists to use when verifying client certificates. + + crlfile= File of additional CRL lists to use when verifying + the client certificate, in addition to CRLs stored in + the capath. Implies VERIFY_CRL flag below. + + dhparams= File containing DH parameters for temporary/ephemeral + DH key exchanges. + + sslflags= Various flags modifying the use of SSL: + DELAYED_AUTH + Don't request client certificates + immediately, but wait until acl processing + requires a certificate (not yet implemented). + NO_DEFAULT_CA + Don't use the default CA lists built in + to OpenSSL. + NO_SESSION_REUSE + Don't allow for session reuse. Each connection + will result in a new SSL session. + VERIFY_CRL + Verify CRL lists when accepting client + certificates. + VERIFY_CRL_ALL + Verify CRL lists for all certificates in the + client certificate chain. + + sslcontext= SSL session ID context identifier. + + generate-host-certificates[=] + Dynamically create SSL server certificates for the + destination hosts of bumped SSL requests.When + enabled, the cert and key options are used to sign + generated certificates. Otherwise generated + certificate will be selfsigned. + If there is CA certificate life time of generated + certificate equals lifetime of CA certificate. If + generated certificate is selfsigned lifetime is three + years. + This option is enabled by default when SslBump is used. + See the sslBump option above for more information. + + dynamic_cert_mem_cache_size=SIZE + Approximate total RAM size spent on cached generated + certificates. If set to zero, caching is disabled. The + default value is 4MB. An average XXX-bit certificate + consumes about XXX bytes of RAM. + + See http_port for a list of available options. DOC_END NAME: tcp_outgoing_tos tcp_outgoing_ds tcp_outgoing_dscp diff --cc src/client_side.cc index 17a6493c3f,2b9d35adbf..e029983043 --- a/src/client_side.cc +++ b/src/client_side.cc @@@ -2447,85 -2444,6 +2453,86 @@@ ConnStateData::clientAfterReadingReques readSomeData(); } +void +ConnStateData::quitAfterError(HttpRequest *request) +{ + // From HTTP p.o.v., we do not have to close after every error detected + // at the client-side, but many such errors do require closure and the + // client-side code is bad at handling errors so we play it safe. + if (request) + request->flags.proxy_keepalive = 0; + flags.readMore = false; + debugs(33,4, HERE << "Will close after error: " << clientConnection); +} + +#if USE_SSL +bool ConnStateData::serveDelayedError(ClientSocketContext *context) +{ + ClientHttpRequest *http = context->http; + StoreEntry *e = bumpServerFirstErrorEntry(); + if (!e) + return false; + + if (!e->isEmpty()) { + quitAfterError(http->request); + + //Failed? Here we should get the error from conn and send it to client + // The error stored in ConnStateData::bumpFirstEntry, replace the + // ClientHttpRequest store entry with this. + clientStreamNode *node = context->getClientReplyContext(); + clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); + assert (repContext); + debugs(33, 5, "Connection first has failed for " << http->uri << ". Respond with an error"); + repContext->setReplyToStoreEntry(e); + context->pullData(); + return true; + } + + // We are in ssl-bump first mode. We have not the server connect name when + // we connected to server so we have to check certificates subject with our server name + if (X509 *server_cert = getBumpServerCert()) { + HttpRequest *request = http->request; + if (!Ssl::checkX509ServerValidity(server_cert, request->GetHost())) { + debugs(33, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate does not match domainname " << request->GetHost()); + + ACLFilledChecklist check(Config.ssl_client.cert_error, request, dash_str); + check.sslErrorList = new Ssl::Errors(SQUID_X509_V_ERR_DOMAIN_MISMATCH); + if (Comm::IsConnOpen(pinning.serverConnection)) + check.fd(pinning.serverConnection->fd); + bool allowDomainMismatch = (check.fastCheck() == ACCESS_ALLOWED); + delete check.sslErrorList; + check.sslErrorList = NULL; + + if (!allowDomainMismatch) { + quitAfterError(request); + + clientStreamNode *node = context->getClientReplyContext(); + clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); + assert (repContext); + + // Create an error object and fill it - ErrorState *err = errorCon(ERR_SECURE_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); ++ ErrorState *err = new ErrorState(ERR_SECURE_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); ++ + err->src_addr = clientConnection->remote; +#ifdef EPROTO + err->xerrno = EPROTO; +#else + err->xerrno = EACCES; +#endif + Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail( SQUID_X509_V_ERR_DOMAIN_MISMATCH, server_cert, NULL); + err->detail = errDetail; + repContext->setReplyToError(request->method, err); + assert(context->http->out.offset == 0); + context->pullData(); + return true; + } + } + } + + return false; +} +#endif //USE_SSL + static void clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *context, const HttpRequestMethod& method, HttpVersion http_ver) { @@@ -2621,11 -2539,14 +2628,17 @@@ request->flags.accelerated = http->flags.accel; request->flags.sslBumped = conn->switchedToHttps(); + request->flags.canRePin = request->flags.sslBumped && conn->pinning.pinned; request->flags.ignore_cc = conn->port->ignore_cc; - request->flags.no_direct = request->flags.accelerated ? !conn->port->allow_direct : 0; + // TODO: decouple http->flags.accel from request->flags.sslBumped + request->flags.no_direct = (request->flags.accelerated && !request->flags.sslBumped) ? + !conn->port->allow_direct : 0; + #if USE_AUTH + if (request->flags.sslBumped) { + if (conn->auth_user_request != NULL) + request->auth_user_request = conn->auth_user_request; + } + #endif /** \par * If transparent or interception mode is working clone the transparent and interception flags @@@ -3593,34 -3454,14 +3610,34 @@@ httpsAccept(const CommAcceptCbParams &p incoming_sockets_accepted++; // Socket is ready, setup the connection manager to start using it - ConnStateData *connState = connStateCreate(params.conn, &s->http); + ConnStateData *connState = connStateCreate(params.conn, s); - typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = JobCallback(33, 5, - TimeoutDialer, connState, ConnStateData::requestTimeout); - commSetConnTimeout(params.conn, Config.Timeout.request, timeoutCall); + if (s->sslBump) { + debugs(33, 5, "httpsAccept: accept transparent connection: " << params.conn); - Comm::SetSelect(params.conn->fd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0); + if (!Config.accessList.ssl_bump) { + httpsSslBumpAccessCheckDone(ACCESS_DENIED, connState); + return; + } + + // Create a fake HTTP request for ssl_bump ACL check, + // using tproxy-provided destination IP and port. + HttpRequest *request = new HttpRequest(); + static char ip[MAX_IPSTRLEN]; + assert(params.conn->flags & (COMM_TRANSPARENT | COMM_INTERCEPTION)); + request->SetHost(params.conn->local.NtoA(ip, sizeof(ip))); + request->port = params.conn->local.GetPort(); + request->myportname = s->name; + + ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(Config.accessList.ssl_bump, request, NULL); + acl_checklist->src_addr = params.conn->remote; + acl_checklist->my_addr = s->s; + acl_checklist->nonBlockingCheck(httpsSslBumpAccessCheckDone, connState); + return; + } else { + SSL_CTX *sslContext = s->staticSslContext.get(); + httpsEstablish(connState, sslContext); + } } void @@@ -3985,27 -3695,11 +4002,27 @@@ clientHttpsConnectionsOpen(void continue; } + // TODO: merge with similar code in clientHttpConnectionsOpen() + if (s->sslBump && !Config.accessList.ssl_bump) { - debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << s->protocol << "_port " << s->http.s); ++ debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << s->protocol << "_port " << s->s); + s->sslBump = 0; + } + + if (s->sslBump && !s->staticSslContext && !s->generateHostCertificates) { - debugs(1, DBG_IMPORTANT, "Will not bump SSL at http_port " << s->http.s << " due to SSL initialization failure."); ++ debugs(1, DBG_IMPORTANT, "Will not bump SSL at http_port " << s->s << " due to SSL initialization failure."); + s->sslBump = 0; + } + + if (s->sslBump) { + // Create ssl_ctx cache for this port. + Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits::max() ? 4194304 : s->dynamicCertMemCacheSize); + } + // Fill out a Comm::Connection which IPC will open as a listener for us - s->http.listenConn = new Comm::Connection; - s->http.listenConn->local = s->http.s; - s->http.listenConn->flags = COMM_NONBLOCKING | (s->http.spoof_client_ip ? COMM_TRANSPARENT : 0) | - (s->http.intercepted ? COMM_INTERCEPTION : 0); + s->listenConn = new Comm::Connection; + s->listenConn->local = s->s; + s->listenConn->flags = COMM_NONBLOCKING | (s->spoof_client_ip ? COMM_TRANSPARENT : 0) | + (s->intercepted ? COMM_INTERCEPTION : 0); // setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS typedef CommCbFunPtrCallT AcceptCall; @@@ -4178,10 -3872,9 +4195,11 @@@ CBDATA_CLASS_INIT(ConnStateData) ConnStateData::ConnStateData() : AsyncJob("ConnStateData"), - closing_(false) +#if USE_SSL - ,switchedToHttps_(false) + switchedToHttps_(false), +#endif + stoppedSending_(NULL), + stoppedReceiving_(NULL) { pinning.pinned = false; pinning.auth = false; diff --cc src/client_side.h index 065729d93a,78cac6bd12..78626e1a7b --- a/src/client_side.h +++ b/src/client_side.h @@@ -364,23 -348,15 +371,27 @@@ private // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :( CBDATA_CLASS2(ConnStateData); - bool closing_; +#if USE_SSL bool switchedToHttps_; + /// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests + String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request + String sslCommonName; ///< CN name for SSL certificate generation + String sslBumpCertKey; ///< Key to use to store/retrieve generated certificate + + /// a job that connects to the HTTPS server to get its SSL certificate + CbcPointer httpsPeeker; + StoreEntry *bumpErrorEntry; + Ssl::X509_Pointer bumpServerCert; + Ssl::Errors *bumpSslErrorNoList; ///< The list of SSL certificate errors which ignored + Ssl::CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use +#endif + /// the reason why we no longer write the response or nil + const char *stoppedSending_; + /// the reason why we no longer read the request or nil + const char *stoppedReceiving_; + - String sslHostName; ///< Host name for SSL certificate generation AsyncCall::Pointer reader; ///< set when we are reading BodyPipe::Pointer bodyPipe; // set when we are reading request body }; diff --cc src/client_side_reply.h index a298815ccf,4f79f46851..7eac9ea302 --- a/src/client_side_reply.h +++ b/src/client_side_reply.h @@@ -71,11 -71,9 +71,11 @@@ public void identifyFoundObject(StoreEntry *entry); int storeOKTransferDone() const; int storeNotOKTransferDone() const; + /// Replaces the store entry with the given and awaiting the client side to read it + void setReplyToStoreEntry(StoreEntry *entry); void setReplyToError(err_type, http_status, const HttpRequestMethod&, char const *, Ip::Address &, HttpRequest *, const char *, #if USE_AUTH - AuthUserRequest::Pointer); + Auth::UserRequest::Pointer); #else void * unused); #endif diff --cc src/client_side_request.cc index 1ccc80711f,ca38f2f5a4..a6f3303b17 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@@ -1373,11 -1421,12 +1422,17 @@@ ClientHttpRequest::sslBumpEstablish(com return; } + // We lack HttpReply which logRequest() uses to log the status code. + // TODO: Use HttpReply instead of the "200 Connection established" string. + al.http.code = 200; + + #if USE_AUTH + // Preserve authentication info for the ssl-bumped request + if (request->auth_user_request != NULL) + getConn()->auth_user_request = request->auth_user_request; + #endif - getConn()->switchToHttps(request->GetHost()); ++ + getConn()->switchToHttps(request->GetHost(), request->port); } void diff --cc src/forward.cc index b10bbc92ba,e78081b5fa..70c1551d1a --- a/src/forward.cc +++ b/src/forward.cc @@@ -122,10 -121,15 +122,10 @@@ void FwdState::start(Pointer aSelf // Bug 3243: CVE 2009-0801 // Bypass of browser same-origin access control in intercepted communication // To resolve this we must force DIRECT and only to the original client destination. - if (Config.onoff.client_dst_passthru && request && !request->flags.redirected && - (request->flags.intercepted || request->flags.spoof_client_ip)) { + const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.spoof_client_ip); + const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified); + if (isIntercepted && useOriginalDst) { - Comm::ConnectionPointer p = new Comm::Connection(); - p->remote = clientConn->local; - p->peerType = ORIGINAL_DST; - getOutgoingAddress(request, p); - serverDestinations.push_back(p); - + selectPeerForIntercepted(); - // destination "found". continue with the forwarding. startConnectionOrFail(); } else { diff --cc src/ssl/ServerPeeker.cc index 641bdd3245,0000000000..b01a750e1d mode 100644,000000..100644 --- a/src/ssl/ServerPeeker.cc +++ b/src/ssl/ServerPeeker.cc @@@ -1,63 -1,0 +1,63 @@@ +/* + * $Id$ + * + * DEBUG: section 33 Client-side Routines + * + */ + - #include "config.h" ++#include "squid.h" + +#include "client_side.h" +#include "forward.h" +#include "ssl/ServerPeeker.h" +#include "Store.h" + + +CBDATA_NAMESPACED_CLASS_INIT(Ssl, ServerPeeker); + + +Ssl::ServerPeeker::ServerPeeker(ConnStateData *anInitiator, + const char *host, const int port): + AsyncJob("Ssl::ServerPeeker"), + initiator(anInitiator), + clientConnection(anInitiator->clientConnection), + request(new HttpRequest) +{ + debugs(33, 4, HERE << "will peek at " << host << ':' << port); + request->flags.sslPeek = 1; + request->SetHost(host); + request->port = port; + request->protocol = AnyP::PROTO_HTTPS; + request->clientConnectionManager = initiator; + const char *uri = urlCanonical(request); + entry = storeCreateEntry(uri, uri, request->flags, request->method); +} + +Ssl::ServerPeeker::~ServerPeeker() +{ + if (entry) + entry->unlock(); +} + +void +Ssl::ServerPeeker::start() +{ + FwdState::fwdStart(clientConnection, entry, request); +} + +void Ssl::ServerPeeker::noteHttpsPeeked(Comm::ConnectionPointer &serverConnection) +{ + assert(initiator.raw()); + initiator.clear(); // will trigger the end of the job +} + +bool +Ssl::ServerPeeker::doneAll() const +{ + return !initiator.valid() && AsyncJob::doneAll(); +} + +void +Ssl::ServerPeeker::swanSong() +{ +} diff --cc src/ssl/crtd_message.cc index 3ba5118cb1,de4f70df15..47ed6ed09a --- a/src/ssl/crtd_message.cc +++ b/src/ssl/crtd_message.cc @@@ -2,8 -2,7 +2,8 @@@ * $Id$ */ - #include "config.h" + #include "squid.h" +#include "ssl/gadgets.h" #include "ssl/crtd_message.h" #if HAVE_CSTDLIB #include diff --cc src/structs.h index be0b42dd4a,4351027fce..ebed2bfccc --- a/src/structs.h +++ b/src/structs.h @@@ -1009,7 -963,9 +965,7 @@@ struct _iostats struct request_flags { - request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),pinned(0),canRePin(0),chunked_reply(0),stream_error(0),sslPeek(0),sslBumped(0),destinationIPLookedUp_(0) { - request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0), - hostVerified(0), - spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),chunked_reply(0),stream_error(0),sslBumped(0),destinationIPLookedUp_(0) { ++ request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),hostVerified(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),pinned(0),canRePin(0),chunked_reply(0),stream_error(0),sslPeek(0),sslBumped(0),destinationIPLookedUp_(0) { #if USE_HTTP_VIOLATIONS nocache_hack = 0; #endif