- All Implemented Interfaces:
Runnable, EventDispatcher
- Direct Known Subclasses:
I2PTunnelConnectClient, I2PTunnelHTTPClient
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static enumAuthentication result status for HTTP client connections.private static classTracks nonce values for digest authentication.protected classCallback for successful proxy connections.protected classCallback for timeout events.Field Summary
Modifier and TypeFieldDescriptionprotected static final AtomicLongCounter for unique request IDs.private static final booleanAvailable as of Java 6 and Android API 9.private StringThe last HTTP proxy that failed.private StringThe last HTTPS proxy that failed.private final AtomicIntegerCounter scheduling the nonce cleanup.private final ConcurrentHashMap<String, I2PTunnelHTTPClientBase.NonceInfo> Used nonces, by user name.Selected HTTP proxy, by clearnet host.List of configured outproxies.private final byte[]The nonce this tunnel issues with.Selected HTTPS proxy, by clearnet host.Digest arguments whose values are credential material and are replaced wholesale before logging.static final StringBasic auth type constant.protected static final intSocket read timeout for a browser fetch, four hours as a failsafe.private static final StringThese strings go in the jar, not the war.protected static final int-1 (forever) as of 0.9.36, so that large POSTs won't timeout on the read side.static final StringDigest auth type constant.private static final StringHeaders of the proxy authentication error response.private static final StringBody of the proxy authentication error response.protected static final StringError response when destination is not found.protected static final StringError response when no outproxy is configured.protected static final intThis is a standard soTimeout, not a total timeout.private static final intMaximum length of an attacker-supplied value (e.g.private static final longAge after which a used nonce is forgotten.private static final intNonces tracked per user.private static final intNonce size in bytes (date + SHA256).static final StringAll auth.static final StringOutproxy auth property.static final StringOutproxy password property.static final StringOutproxy password property prefix.static final StringOutproxy username property.static final StringPasswords for specific outproxies may be added withoutproxyUsername.fooproxy.i2p=user andoutproxyPassword.fooproxy.i2p=pw.static final StringNew style MD5 auth.static final StringSHA-256 digest suffix.static final StringMD5 digest suffix.static final StringProxy password property.static final StringAdditional users may be added with proxyPassword.user=pw.static final StringProperty for SSL outproxies.static final StringProperty to use local outproxy plugin.static final StringProxy username property.private static final intLength of the proxy nonce, in bytes.private static final intLength of a SHA-256 hash, in bytes.(package private) static final StringCookie that counts meta-refresh retries on a shed connection.(package private) static final intHow many meta-refresh pages to serve before the final 503.(package private) static final intShort SO_TIMEOUT while reading the shed request head (never on the hot path).(package private) static final intRefresh delay in seconds for the intermediate shed page.private static final StringThe platform file separator.protected static final StringHTTP 200 response for established CONNECT tunnels.Fields inherited from class I2PTunnelClientBase
_clientId, _context, _executor, _log, _ownDest, DEFAULT_CONNECT_TIMEOUT, DEFAULT_MAX_CONNECTIONS, DEFAULT_SOCKET_OPEN_TIMEOUT, dest, l, listenerReady, MAX_TIMEOUT_FAILOVER, MIN_CONNECT_LEG_MS, mySockets, NO_DEADLINE, POOL_BUILD_DEADLINE_GRACE_MS, PROP_MAX_CONNECTIONS, PROP_USE_SSL, REQUEST_CONNECT_DEADLINE_MS, sockLock, sockMgr, ssModifier and TypeFieldDescriptionprotected longThis client's ID.protected final I2PAppContextThe application context.protected ThreadPoolExecutorThread pool executor.protected final LogThe logger.protected booleanWhether we own our destination.(package private) static final longDefault connect timeout.static final intDefault cap on concurrently handled client connections.static final longDefault socket open timeout in ms, after whichI2PTunnelClientBase.close(boolean)will proceed even with active sockets.protected DestinationThe destination.protected final LoggingThe logging instance.protected booleanProtected for I2Ping since 0.9.11.(package private) static final intLegacy cap on consecutive connect timeouts before abandoning tunnel failover.(package private) static final longMinimum remaining budget for starting one connect leg.List of active sockets.(package private) static final longDeadline sentinel for callers that have not adopted the shared request budget (SOCKS, IRC, DCC, rawcreateI2PSocket): they keep their original per-call limits because this sentinel never reads as expired and never clamps.(package private) static final longOne-shot deadline extension granted while the outbound tunnel pool is still building (poolState() == 0) when the shared budget runs out.static final StringProperty name: max concurrently active client connections handled by one client tunnel.static final StringProperty turning on SSL between the proxy and the client.(package private) static final longSingle wall-clock budget for establishing one proxied request.protected final ObjectGuards sockMgr and mySockets.protected I2PSocketManagerThe socket manager.protected ServerSocketServer socket.Constructor Summary
ConstructorsConstructorDescriptionI2PTunnelHTTPClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel) Create a new HTTP client tunnel.I2PTunnelHTTPClientBase(int localPort, Logging l, I2PSocketManager sktMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) This constructor always starts the tunnel (ignoring thei2cp.delayOpenoption).Method Summary
Modifier and TypeMethodDescriptionprotected StringLook up a translation key in this class's resource bundle.protected StringTranslate with one parameter {0}.protected StringTranslate with two parameters {0} and {1}.(package private) static StringFormat the remote address as IP:PORT for ban and failure logging.protected I2PTunnelHTTPClientBase.AuthResultAuthorization Ref: RFC 2617 If the socket is an InternalSocket, no auth required.(package private) static StringFinal shed response after refresh budget is exhausted (or non-HTML).(package private) static StringbuildShedRefreshResponse(int nextAttempt) Intermediate shed page: unquoted meta refresh (no nested quotes in the tag) plus a Set-Cookie bump so the browser retries at mostSHED_MAX_REFRESHtimes before the final 503.private voidRemove expired nonces from map.static StringdecodeIDNHost(String host) Decode a hostname for display.private static StringdecodeIDNURI(String uri) Decodes Internationalized Domain Names in a URI for display.protected StringgetAuthError(boolean isStale) What to send if digest auth fails.protected StringgetErrorPage(String base, String backup) Load the error page header file, e.g.protected static StringgetErrorPage(I2PAppContext ctx, String base, String backup) Load the error page header file, e.g.private static StringReturns the HTML footer added to error pages.private StringgetNonce()The Base 64 of 40 bytes: (now, sha256 of (now, proxy nonce)).protected StringgetPrefix(long requestId) Generates a unique log prefix for request tracking.protected abstract StringgetRealm()Get the authentication realm string.protected voidhandleClientException(Exception ex, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy, long requestId) Handle an exception from a client connection.protected voidhandleI2PSocketException(I2PSocketException ise, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) Generate an error page based on the status code in our custom exception.static booleanisBlockedIPv4Address(String host) Determine whether an IPv4 host is in a blocked non-routable block: loopback, "this network", RFC 1918 private, link-local, carrier-grade NAT, benchmarking, documentation, multicast, and reserved space.static booleanisBlockedLocalAddress(String host) Determine whether a proxy request target is a loopback, private, link-local, shared, or otherwise non-routable address that must not be reached through the proxy.protected booleanChecks if HTTP Digest authentication is required by the outproxy.protected voidnoteProxyResult(String proxy, String host, boolean isSSL, boolean ok) Update the cache and note if failed.voidoptionsUpdated(I2PTunnel tunnel) Update the outproxy list then call super.Modified from LoadClientAppsJob.private static int[]parseDottedQuad(String host) Parse a strict dotted quad into four octets.private static intParse one IPv6 group of up to four hex digits.private static int[]Parse an IPv6 address into its eight 16-bit groups, expanding "::" and converting an embedded IPv4 tail.(package private) static intparseShedAttempt(String cookie) How many shed meta-refresh attempts the request's Cookie header already used.private static StringreadFile(I2PAppContext ctx, File file) Reads a small text file into a string.sanitizeAuthArgs(Map<String, String> args) Copy digest request arguments into a form safe to log: credential material is redacted, and every remaining value is stripped of line breaks and capped, so a hostile upstream cannot forge extra log lines or grow the log without bound.(package private) static StringsanitizeLogValue(String value) Strip line breaks and cap the length of an attacker-supplied value before it is written to the log, so a hostile username cannot forge extra log lines.protected StringselectProxy(String host) Selects an appropriate outproxy for the given host from the proxy pool.private StringselectProxy(String host, Object lock, List<String> proxies, String lastFailed, Map<String, String> cache, String logPrefix) Select an outproxy for the given host with load balancing.protected StringselectSSLProxy(String host) Selects an SSL-capable outproxy for HTTPS connections.(package private) static booleanshouldMetaRefresh(String method, String accept, int attempt) Whether a shed connection should get a meta-refresh page instead of a 503.(package private) static StringsummarizeAuthorization(String authorization) Summarize an Authorization header for logging without disclosing credential material.Verify all of it.verifyNonce(String b64, String ncs) Verify the Base 64 of 40 bytes: (now, sha256 of (now, proxy nonce)) and the nonce count.protected voidwriteErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) No jump servers or extra message.protected voidwriteErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) No extra message.protected voidwriteErrorMessage(String errMessage, String extraMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) No jump servers.protected voidwriteErrorMessage(String errMessage, String extraMessage, OutputStream outs, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) Write the complete error message to the output stream.static voidwriteFooter(OutputStream out) Write the closing HTML footer and flush it down the stream.static voidwriteFooter(Writer out) Write the closing HTML footer and flush it down the writer.protected voidWrite a real HTTP status on a shed connection so the browser never sees an empty response: HTML GET navigations get a cookie-capped meta-refresh page (up toSHED_MAX_REFRESHtimes), everything else gets a 503.Methods inherited from class I2PTunnelClientBase
buildSocketManager, buildSocketManager, buildSocketManager, buildSocketManager, clampToDeadlineMs, clientConnectionRun, close, closeSocket, connectDeadlineFrom, createI2PSocket, createI2PSocket, createI2PSocket, createI2PSocket, destroy, extendDeadlineForBuildingPool, getDefaultOptions, getDefaultOptions, getEffectiveMaxConnections, getListenHost, getLocalPort, getSocketManager, getSocketManager, getSocketOpenTimeout, isConnectTimeout, isDeadlineExpired, legConnectTimeoutMs, manageConnection, poolIsDefinitivelyDown, poolState, resolveEffectiveMaxConnections, resolveMaxConnections, resolveRunnerCeiling, run, shouldContinueFailover, shouldContinueFailover, shouldOuterRetryConnect, shouldOuterRetryConnect, startRunning, verifySocketManagerModifier and TypeMethodDescriptionprotected I2PSocketManagerFor NON-SHARED clients (ownDest = true).protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel) Create a disconnected socket manager for the tunnel, with no private key file.protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel, String pkf) Create a disconnected socket manager for the tunnel, loading the persistent client dest from pkf if it is non-null.protected static I2PSocketManagerbuildSocketManager(I2PTunnel tunnel, String pkf, Logging log) Create a disconnected socket manager for the tunnel, loading the persistent client dest from pkf if it is non-null, and logging any key file error to log.(package private) static longclampToDeadlineMs(long requestedMs, long deadlineMs, long nowMs) Clamp a requested timeout to the time left before a shared deadline.protected abstract voidManage a connection in a separate thread.booleanclose(boolean forced) Note that the tunnel can be reopened after this by calling startRunning().static voidClose a socket silently.(package private) static longconnectDeadlineFrom(long nowMs) Compute the shared connect deadline for a request starting now.createI2PSocket(Destination dest) Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.createI2PSocket(Destination dest, int port) Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.createI2PSocket(Destination dest, I2PSocketOptions opt) Create a new I2PSocket towards to the specified destination, adding it to the list of connections actually managed by this tunnel.(package private) I2PSocketcreateI2PSocket(Destination dest, I2PSocketOptions opt, long deadlineMs) Create a new I2PSocket bounded by a shared request deadline.booleandestroy()Note that the tunnel cannot be reopened after this by calling startRunning(), as it will destroy the underlying socket manager.(package private) static longextendDeadlineForBuildingPool(long deadlineMs, long nowMs, int poolState, boolean alreadyExtended) One-shot deadline extension for a request whose outbound tunnel pool is still building when the shared deadline runs out.protected I2PSocketOptionsCreate the default options (using the default timeout, etc).protected I2PSocketOptionsgetDefaultOptions(Properties overrides) Create the default options (using the default timeout, etc).(package private) intThe effective concurrent-connection cap for this tunnel at the moment the accept loop admits a connection.protected final InetAddressGet the listen host address.final intGet the local port.Returns the I2PSocketManager for this task.protected static I2PSocketManagergetSocketManager(I2PTunnel tunnel, String pkf) This is ONLY for shared clients.longReturns the socket open timeout in ms; close() will proceed after this even with active sockets.(package private) static booleanFor timeout wording.(package private) static booleanisDeadlineExpired(long deadlineMs, long nowMs) Whether a shared connect deadline has passed.(package private) static longlegConnectTimeoutMs(long requestedMs, long deadlineMs, long nowMs) Compute the connect timeout to apply to one failover leg under a shared deadline.protected voidManage the connection just opened on the specified socket.protected booleanAnd none are being built, so further connect retries cannot succeed.protected intRouter-context only, best-effort check of the client outbound tunnel pool.(package private) static intresolveEffectiveMaxConnections(boolean customized, int ownCap, int globalDefault) Pure decision helper forI2PTunnelClientBase.getEffectiveMaxConnections(): pick the per-tunnel override when one was explicitly configured, otherwise the Tuner-managed default cap.(package private) static intresolveMaxConnections(String configured) Resolve the max-concurrent-connections cap from the tunnel's configured value.(package private) static intresolveRunnerCeiling(boolean customized, int effectiveMax) Ceiling to pin on this tunnel's runner pool at creation time.voidrun()Non-final since 0.9.11.(package private) static booleanshouldContinueFailover(int tunnelCount, int attemptsMade, int timeoutFailures, boolean poolDown) Whether another tunnel-failover attempt is worthwhile after a connect failure.(package private) static booleanshouldContinueFailover(int tunnelCount, int attemptsMade, int timeoutFailures, boolean poolDown, boolean poolBuilding) Whether another tunnel-failover attempt is worthwhile after a connect failure.(package private) static booleanshouldOuterRetryConnect(int connectAttempts, int timeoutConnectAttempts, boolean timedOut, boolean poolDown, boolean poolBuilding, boolean browserClosed) Whether the outer HTTP connect loop should retry after a failure.(package private) static booleanshouldOuterRetryConnect(int connectAttempts, int timeoutConnectAttempts, boolean timedOut, int poolState, boolean deadlineExpired) Whether the outer HTTP connect loop should retry after a failure, given the single pool-state snapshot taken for that failure.voidActually open the local socket and start working on incoming connections.protected voidCreate the manager if it doesn't exist, AND connect it to the router and build tunnels.Methods inherited from class I2PTunnelTask
connected, disconnected, errorOccurred, getBooleanOption, getId, getTunnel, isOpen, reportAbuse, routerDisconnected, setId, setName, setTunnel, toStringModifier and TypeMethodDescriptionvoidconnected(I2PSession session) For tasks that don't callI2PTunnel.addSession(I2PSession)directly.voiddisconnected(I2PSession session) Called when a session is disconnected.voiderrorOccurred(I2PSession session, String message, Throwable error) Does nothing here.protected booleangetBooleanOption(String opt, boolean dflt) Read a boolean client option from the tunnel's properties.intgetId()The id of the client list entry for this task.The I2PTunnel this task runs inside.booleanisOpen()Whether the tunnel is running and accepting connections.voidreportAbuse(I2PSession session, int severity) Does nothing here.protected voidTell the tunnel that the router connection has dropped.voidsetId(int id) Record the client list entry id for this task.protected voidRecord the display name for this task.voidRebind this task to a different tunnel.toString()The display name given to this task when it was constructed.Methods inherited from class EventDispatcherImpl
attachEventDispatcher, detachEventDispatcher, getEventDispatcher, getEvents, getEventValue, ignoreEvents, notifyEvent, unIgnoreEvents, waitEventValueModifier and TypeMethodDescriptionvoidAttach an EventDispatcher object to the events dispatching chain.voidDetach the specified EventDispatcher object from the events dispatching chain.Object to be used to deliver events (usuallythis, but YMMV).Retrieve the names of all the events that have been received.getEventValue(String name) Retrieve the value currently associated with the specified event value.voidIgnore further event notifications.voidnotifyEvent(String eventName, Object args) Deliver an event.voidAlmost like the method above :-).waitEventValue(String name) Wait until the given event has received a value.
Field Details
PROXYNONCE_BYTES
private static final int PROXYNONCE_BYTESLength of the proxy nonce, in bytes.- See Also:
SHA256_BYTES
private static final int SHA256_BYTESLength of a SHA-256 hash, in bytes.- See Also:
NONCE_BYTES
private static final int NONCE_BYTESNonce size in bytes (date + SHA256).- See Also:
MAX_NONCE_AGE
private static final long MAX_NONCE_AGEAge after which a used nonce is forgotten.- See Also:
MAX_NONCE_COUNT
PROP_USE_OUTPROXY_PLUGIN
Property to use local outproxy plugin.- See Also:
PROP_SSL_OUTPROXIES
Property for SSL outproxies.- See Also:
SLASH
The platform file separator.INITIAL_SO_TIMEOUT
protected static final int INITIAL_SO_TIMEOUTThis is a standard soTimeout, not a total timeout. We have no slowloris protection on the client side. See I2PTunnelHTTPServer or SAM's ReadLine if we need that.- See Also:
SHED_COOKIE
Cookie that counts meta-refresh retries on a shed connection.- See Also:
SHED_MAX_REFRESH
static final int SHED_MAX_REFRESHHow many meta-refresh pages to serve before the final 503.- See Also:
SHED_REFRESH_SECONDS
static final int SHED_REFRESH_SECONDSRefresh delay in seconds for the intermediate shed page.- See Also:
SHED_READ_TIMEOUT_MS
static final int SHED_READ_TIMEOUT_MSShort SO_TIMEOUT while reading the shed request head (never on the hot path).- See Also:
BROWSER_READ_TIMEOUT
protected static final int BROWSER_READ_TIMEOUTSocket read timeout for a browser fetch, four hours as a failsafe.- See Also:
ERR_AUTH1
Headers of the proxy authentication error response.- See Also:
ERR_AUTH2
Body of the proxy authentication error response.- See Also:
_proxyList
ERR_NO_OUTPROXY
Error response when no outproxy is configured.- See Also:
ERR_DESTINATION_UNKNOWN
Error response when destination is not found.- See Also:
SUCCESS_RESPONSE
HTTP 200 response for established CONNECT tunnels.- See Also:
_proxyNonce
private final byte[] _proxyNonceThe nonce this tunnel issues with._nonces
Used nonces, by user name._nonceCleanCounter
Counter scheduling the nonce cleanup._proxyCache
_lastFailedProxy
The last HTTP proxy that failed._proxySSLCache
_lastFailedSSLProxy
The last HTTPS proxy that failed._haveIDN
private static final boolean _haveIDNAvailable as of Java 6 and Android API 9.DEFAULT_READ_TIMEOUT
protected static final int DEFAULT_READ_TIMEOUT-1 (forever) as of 0.9.36, so that large POSTs won't timeout on the read side.- See Also:
__requestId
Counter for unique request IDs.PROP_AUTH
PROP_USER
PROP_PW
PROP_PW_PREFIX
Additional users may be added with proxyPassword.user=pw.- See Also:
PROP_OUTPROXY_AUTH
PROP_OUTPROXY_USER
Outproxy username property.- See Also:
PROP_OUTPROXY_PW
Outproxy password property.- See Also:
PROP_OUTPROXY_USER_PREFIX
Passwords for specific outproxies may be added withoutproxyUsername.fooproxy.i2p=user andoutproxyPassword.fooproxy.i2p=pw.- See Also:
PROP_OUTPROXY_PW_PREFIX
Outproxy password property prefix.- See Also:
PROP_PROXY_DIGEST_PREFIX
New style MD5 auth.- See Also:
PROP_PROXY_DIGEST_SUFFIX
PROP_PROXY_DIGEST_SHA256_SUFFIX
SHA-256 digest suffix.- See Also:
BASIC_AUTH
DIGEST_AUTH
MAX_LOG_VALUE
private static final int MAX_LOG_VALUEMaximum length of an attacker-supplied value (e.g. a username) echoed to the log.- See Also:
AUTH_REDACTED_KEYS
Digest arguments whose values are credential material and are replaced wholesale before logging. The response hash is replayable inside its nonce window. The username and nonce pair identifies the credential being targeted; cnonce is the client half of the nonce.BUNDLE_NAME
These strings go in the jar, not the war.- See Also:
Constructor Details
I2PTunnelHTTPClientBase
public I2PTunnelHTTPClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel) throws IllegalArgumentException Create a new HTTP client tunnel.- Parameters:
localPort- the local port to bind toownDest- whether to use our own destinationl- the Logging instance this tunnel's status messages are sent tonotifyThis- event dispatcher for notificationshandlerName- the handler nametunnel- the parent I2PTunnel instance- Throws:
IllegalArgumentException
I2PTunnelHTTPClientBase
public I2PTunnelHTTPClientBase(int localPort, Logging l, I2PSocketManager sktMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) throws IllegalArgumentException This constructor always starts the tunnel (ignoring thei2cp.delayOpenoption). It is used to add a client to an existing socket manager.- Parameters:
localPort- the local port to bind tol- the Logging instance this tunnel's status messages are sent tosktMgr- the existing socket managertunnel- the parent I2PTunnel instancenotifyThis- event dispatcher for notificationsclientId- the client identifier- Throws:
IllegalArgumentException
Method Details
getPrefix
Generates a unique log prefix for request tracking.This method creates a consistent prefix string that includes the request ID for correlating log entries across multiple threads and connections.
- Parameters:
requestId- the unique identifier for this request- Returns:
- a formatted string suitable for logging
selectProxy
Selects an appropriate outproxy for the given host from the proxy pool.The selection is random, but sticky per host: the first chosen proxy for a host is cached and reused. Failed proxies are remembered and temporarily skipped.
- Parameters:
host- the target hostname to route through the outproxy (may be used for stickiness)- Returns:
- the selected proxy destination string (Base32 address), or null if no proxies configured
- See Also:
selectSSLProxy
Selects an SSL-capable outproxy for HTTPS connections.This method is similar to
selectProxy(String)but only considers outproxies configured for SSL support (viai2ptunnel.httpclient.SSLOutproxies).Unlike selectProxy(), we parse the option on the fly so it can be changed without restart. ConnectClient should use selectProxy().
- Parameters:
host- the target hostname (may be used for proxy stickiness)- Returns:
- the selected SSL proxy destination, or null if none configured
- See Also:
selectProxy
private String selectProxy(String host, Object lock, List<String> proxies, String lastFailed, Map<String, String> cache, String logPrefix) Select an outproxy for the given host with load balancing. Failed proxies are remembered and temporarily skipped.- Parameters:
host- the target hostname (may be used for proxy stickiness)lock- the monitor guarding the proxy stateproxies- the configured outproxieslastFailed- the last failed proxy, or nullcache- clearnet host to proxy stickiness cachelogPrefix- the message prefix- Returns:
- the selected proxy destination string, or null if none configured
noteProxyResult
getRealm
optionsUpdated
Update the outproxy list then call super.- Overrides:
optionsUpdatedin classI2PTunnelClientBase- Parameters:
tunnel- the tunnel whose client options were updated
isDigestAuthRequired
protected boolean isDigestAuthRequired()Checks if HTTP Digest authentication is required by the outproxy.This method checks the configured authentication requirements and determines whether the current request requires digest authentication.
- Returns:
- true if digest authentication is required, false otherwise
writeShedResponse
Write a real HTTP status on a shed connection so the browser never sees an empty response: HTML GET navigations get a cookie-capped meta-refresh page (up toSHED_MAX_REFRESHtimes), everything else gets a 503. Falls back to a plain 503 if the request head cannot be read in time.- Overrides:
writeShedResponsein classI2PTunnelClientBase- Parameters:
s- the accepted socket being shed; never null
parseShedAttempt
How many shed meta-refresh attempts the request's Cookie header already used.- Parameters:
cookie- the full Cookie header value, or null- Returns:
- parsed attempt count, or 0 when absent/unparseable
shouldMetaRefresh
Whether a shed connection should get a meta-refresh page instead of a 503. Only HTML navigations qualify: GET with an Accept header that asks for text/html, and fewer thanSHED_MAX_REFRESHprior attempts.- Parameters:
method- HTTP method from the request line, or nullaccept- Accept header value, or nullattempt- prior attempts from the shed cookie- Returns:
- true to emit a meta-refresh page
buildShedRefreshResponse
Intermediate shed page: unquoted meta refresh (no nested quotes in the tag) plus a Set-Cookie bump so the browser retries at mostSHED_MAX_REFRESHtimes before the final 503.- Parameters:
nextAttempt- the attempt count to store in the cookie (1-based after increment)- Returns:
- a complete HTTP/1.1 200 response with HTML body
buildShed503Response
Final shed response after refresh budget is exhausted (or non-HTML).- Returns:
- a complete HTTP/1.1 503 response
authorize
protected I2PTunnelHTTPClientBase.AuthResult authorize(Socket s, long requestId, String method, String authorization) Authorization Ref: RFC 2617 If the socket is an InternalSocket, no auth required.- Parameters:
s- the client socketrequestId- the unique request identifier for loggingmethod- GET, POST, etc.authorization- may be null, the full auth line e.g. "Basic lskjlksjf"- Returns:
- AUTH_GOOD when no authorization is required or the supplied credentials were accepted, otherwise AUTH_BAD when they were rejected or AUTH_BAD_REQ when the auth line was malformed
validateDigest
private I2PTunnelHTTPClientBase.AuthResult validateDigest(String method, Map<String, String> args, Socket s) Verify all of it. Ref: RFC 2617.- Parameters:
method- the HTTP method from the request line, hashed as part of the digestargs- the parsed Authorization header parameters, keyed by names- just to log the IP on failure- Returns:
- AUTH_GOOD if everything checks out, otherwise AUTH_BAD, AUTH_STALE or AUTH_BAD_REQ
summarizeAuthorization
Summarize an Authorization header for logging without disclosing credential material. Basic auth carries a decodable user:password pair, so only the scheme and the credential byte count are logged. The scheme is attacker-supplied too, so anything with line breaks (log injection) or an implausible length is replaced.- Parameters:
authorization- the full header value e.g. "Basic dXNlcjpwYXNz" (no "Proxy-Authorization:" prefix), may be null- Returns:
- e.g. "Basic (13 bytes)", never the credentials; "null" if null and "malformed" for a hostile scheme
sanitizeLogValue
sanitizeAuthArgs
Copy digest request arguments into a form safe to log: credential material is redacted, and every remaining value is stripped of line breaks and capped, so a hostile upstream cannot forge extra log lines or grow the log without bound.Non-secret protocol parameters (qop, nc, algorithm, realm, uri) are kept because they are what makes a failed handshake diagnosable, but they are attacker-controlled, so they pass through
sanitizeLogValue(String)rather than being logged raw.- Parameters:
args- the parsed digest arguments, may be null- Returns:
- a sanitized copy, empty map if null
addrAndPort
isBlockedLocalAddress
Determine whether a proxy request target is a loopback, private, link-local, shared, or otherwise non-routable address that must not be reached through the proxy. Non-.i2p hosts are handed to the outproxy plugin, which opens a raw socket from this machine, so a request for 127.0.0.1 or 10.x would otherwise reach the router itself or the LAN.The host is parsed as an address rather than matched with string prefixes, so every address in a blocked block is caught (not only 10.0.x.x or 172.16.x.x) while a name that merely looks similar (10.0.example.com) is not. Bracketed IPv6 literals, zone ids, and v4-mapped forms are normalized first.
Public so the SOCKS4a and SOCKS5 servers, which hand non-.i2p targets to the same outproxy plugin, apply one policy rather than a narrower copy of it.
- Parameters:
host- the request target host, without port, may be null- Returns:
- true if the host must not be proxied to
isBlockedIPv4Address
Determine whether an IPv4 host is in a blocked non-routable block: loopback, "this network", RFC 1918 private, link-local, carrier-grade NAT, benchmarking, documentation, multicast, and reserved space.A host made only of digits and dots that is not a strict dotted quad (127.1, 2130706433) is an ambiguous address literal rather than a name, so it is blocked too; such a host cannot be a resolvable name, as no top-level label may be all-numeric.
- Parameters:
host- the IPv4 host, lowercase, no brackets, may be null- Returns:
- true if blocked
parseDottedQuad
Parse a strict dotted quad into four octets.- Parameters:
host- lowercase host, digits and dots- Returns:
- the octets, or null if not exactly four in-range groups
parseIPv6Groups
Parse an IPv6 address into its eight 16-bit groups, expanding "::" and converting an embedded IPv4 tail.- Parameters:
s- the address, lowercase, without brackets or zone id- Returns:
- the groups, or null if the address does not parse
parseHexGroup
Parse one IPv6 group of up to four hex digits.- Parameters:
s- the group text- Returns:
- the value, or -1 if empty, too long, or non-hex
getNonce
The Base 64 of 40 bytes: (now, sha256 of (now, proxy nonce)).- Returns:
- the Base 64 digest, which is also registered as a valid nonce
verifyNonce
Verify the Base 64 of 40 bytes: (now, sha256 of (now, proxy nonce)) and the nonce count.- Parameters:
b64- nonce non-nullncs- nonce count string non-null- Returns:
- AUTH_GOOD if the nonce is valid and the count is new, otherwise AUTH_BAD or AUTH_STALE
cleanNonces
private void cleanNonces()Remove expired nonces from map.getAuthError
What to send if digest auth fails.- Parameters:
isStale- true if the previous nonce was stale- Returns:
- the HTTP error response string
parseArgs
getErrorPage
Load the error page header file, e.g. foo => errordir/foo-header_xx.ht for lang xx, or errordir/foo-header.ht, or the backup byte array on fail..ht files must be UTF-8 encoded and use \r\n terminators so the HTTP headers are conformant. We can't use
FileUtil.readFile(String, String, OutputStream)because it strips \r.- Parameters:
base- the error page base namebackup- fallback string if the file cannot be read- Returns:
- non-null
getErrorPage
Load the error page header file, e.g. foo => errordir/foo-header_xx.ht for lang xx, or errordir/foo-header.ht, or the backup byte array on fail..ht files must be UTF-8 encoded and use \r\n terminators so the HTTP headers are conformant. We can't use
FileUtil.readFile(String, String, OutputStream)because it strips \r.- Parameters:
ctx- the I2P application contextbase- the error page base namebackup- fallback string if the file cannot be read- Returns:
- non-null
readFile
Reads a small text file into a string.- Parameters:
ctx- the app contextfile- the file to read- Returns:
- the file contents
- Throws:
IOException- if the file cannot be read
handleClientException
protected void handleClientException(Exception ex, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy, long requestId) Handle an exception from a client connection.- Parameters:
ex- may be nullout- the output stream for the error responsetargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destinationrequestId- the request identifier for logging
handleI2PSocketException
protected void handleI2PSocketException(I2PSocketException ise, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) Generate an error page based on the status code in our custom exception.- Parameters:
ise- may be nullout- the output stream for the error responsetargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destination
writeErrorMessage
protected void writeErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) throws IOException No jump servers or extra message.- Parameters:
errMessage- the error headerout- the output streamtargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destination- Throws:
IOException- on write error
writeErrorMessage
protected void writeErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException No extra message.- Parameters:
errMessage- the error headerout- the output streamtargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destinationjumpServers- comma- or space-separated list, or null- Throws:
IOException- on write error
writeErrorMessage
protected void writeErrorMessage(String errMessage, String extraMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) throws IOException No jump servers.- Parameters:
errMessage- the error headerextraMessage- extra message or null, will be HTML-escapedout- the output streamtargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destination- Throws:
IOException- on write error
writeErrorMessage
protected void writeErrorMessage(String errMessage, String extraMessage, OutputStream outs, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException Write the complete error message to the output stream.- Parameters:
errMessage- the error headerextraMessage- extra message or null, will be HTML-escapedouts- the output streamtargetRequest- the original request URIusingWWWProxy- whether a WWW outproxy is in usewwwProxy- the outproxy destinationjumpServers- comma- or space-separated list, or null- Throws:
IOException- on write error
decodeIDNURI
Decodes Internationalized Domain Names in a URI for display.This method converts punycode-encoded hostnames (xn--) in a URI back to their Unicode representation for human-readable display. If IDN support is unavailable or the URI contains no punycode, the original URI is returned unchanged.
- Parameters:
uri- the URI string that may contain encoded hostnames- Returns:
- the URI with decoded hostname, or the original URI on error
decodeIDNHost
_t
_t
_t