diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java index de219ff39b..6e362a41b9 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java @@ -155,6 +155,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R Outproxy outproxy = null; long requestId = __requestId.incrementAndGet(); try { + s.setSoTimeout(INITIAL_SO_TIMEOUT); out = s.getOutputStream(); in = s.getInputStream(); String line, method = null, host = null, destination = null, restofline = null; @@ -283,6 +284,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R } } newRequest.append("\r\n"); // HTTP spec + s.setSoTimeout(0); // do it break; } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index e4c61fed36..8554421cd0 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -393,6 +393,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn boolean shout = false; try { + s.setSoTimeout(INITIAL_SO_TIMEOUT); out = s.getOutputStream(); InputReader reader = new InputReader(s.getInputStream()); String line, method = null, protocol = null, host = null, destination = null; @@ -1040,6 +1041,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } } newRequest.append("Connection: close\r\n\r\n"); + s.setSoTimeout(0); break; } else { newRequest.append(line).append("\r\n"); // HTTP spec diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java index 6365f5d3a9..92cb2dca78 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java @@ -13,6 +13,7 @@ import java.io.Reader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.net.Socket; +import java.net.SocketTimeoutException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -61,6 +62,13 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem private static final int MAX_NONCE_COUNT = 1024; /** @since 0.9.11, moved to Base in 0.9.29 */ public static final String PROP_USE_OUTPROXY_PLUGIN = "i2ptunnel.useLocalOutproxy"; + /** + * This 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. + * @since 0.9.33 + */ + protected static final int INITIAL_SO_TIMEOUT = 15*1000; private static final String ERR_AUTH1 = "HTTP/1.1 407 Proxy Authentication Required\r\n" + @@ -610,7 +618,9 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem if (out == null) return; String header; - if (usingWWWProxy) + if (ex instanceof SocketTimeoutException) + header = I2PTunnelHTTPServer.ERR_REQUEST_TIMEOUT; + else if (usingWWWProxy) header = getErrorPage(I2PAppContext.getGlobalContext(), "dnfp", ERR_DESTINATION_UNKNOWN); else header = getErrorPage(I2PAppContext.getGlobalContext(), "dnf", ERR_DESTINATION_UNKNOWN); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java index 19b15d3ab5..9dbac300cb 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java @@ -156,7 +156,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { "

431 Request header fields too large

\n" + ""; - private final static String ERR_REQUEST_TIMEOUT = + /** @since protected since 0.9.33 for I2PTunnelHTTPClientBase, was private */ + protected final static String ERR_REQUEST_TIMEOUT = "HTTP/1.1 408 Request timeout\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java index 7ad03a021e..824dbea978 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java @@ -7,6 +7,7 @@ package net.i2p.i2ptunnel.socks; import java.net.Socket; +import java.net.SocketException; import java.util.concurrent.atomic.AtomicInteger; import net.i2p.client.streaming.I2PSocket; @@ -48,8 +49,14 @@ public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel { protected void clientConnectionRun(Socket s) { try { //_log.error("SOCKS IRC Tunnel Start"); + try { + s.setSoTimeout(INITIAL_SO_TIMEOUT); + } catch (SocketException ioe) {} SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(_context, s, getTunnel().getClientOptions()); Socket clientSock = serv.getClientSocket(); + try { + s.setSoTimeout(0); + } catch (SocketException ioe) {} I2PSocket destSock = serv.getDestinationI2PSocket(this); StringBuffer expectedPong = new StringBuffer(); int id = __clientId.incrementAndGet(); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java index 94cc817e7a..71c77c93e9 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java @@ -7,6 +7,7 @@ package net.i2p.i2ptunnel.socks; import java.net.Socket; +import java.net.SocketException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,6 +28,14 @@ import net.i2p.util.Log; public class I2PSOCKSTunnel extends I2PTunnelClientBase { + /** + * This 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. + * @since 0.9.33 + */ + protected static final int INITIAL_SO_TIMEOUT = 15*1000; + private HashMap> proxies = null; // port# + "" or "default" -> hostname list //public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest) { @@ -49,8 +58,14 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { protected void clientConnectionRun(Socket s) { try { + try { + s.setSoTimeout(INITIAL_SO_TIMEOUT); + } catch (SocketException ioe) {} SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(_context, s, getTunnel().getClientOptions()); Socket clientSock = serv.getClientSocket(); + try { + s.setSoTimeout(0); + } catch (SocketException ioe) {} I2PSocket destSock = serv.getDestinationI2PSocket(this); Thread t = new I2PTunnelRunner(clientSock, destSock, sockLock, null, null, mySockets, (I2PTunnelRunner.FailCallback) null); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java index a2789b188c..fd99ce1699 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java @@ -71,7 +71,7 @@ class SOCKS4aServer extends SOCKSServer { manageRequest(in, out); } catch (IOException e) { - throw new SOCKSException("Connection error (" + e.getMessage() + ")"); + throw new SOCKSException("Connection error", e); } setupCompleted = true; @@ -150,7 +150,7 @@ class SOCKS4aServer extends SOCKSServer { sendRequestReply(Reply.SUCCEEDED, InetAddress.getByName("127.0.0.1"), 1, out); } catch (IOException e) { - throw new SOCKSException("Connection error (" + e.getMessage() + ")"); + throw new SOCKSException("Connection error", e); } } @@ -201,7 +201,7 @@ class SOCKS4aServer extends SOCKSServer { try { out = new DataOutputStream(clientSock.getOutputStream()); } catch (IOException e) { - throw new SOCKSException("Connection error (" + e.getMessage() + ")"); + throw new SOCKSException("Connection error", e); } // FIXME: here we should read our config file, select an @@ -286,19 +286,17 @@ class SOCKS4aServer extends SOCKSServer { try { sendRequestReply(Reply.CONNECTION_REFUSED, InetAddress.getByName("127.0.0.1"), 0, out); } catch (IOException ioe) {} - throw new SOCKSException("Error in destination format"); + throw new SOCKSException("Error in destination format", e); } catch (IOException e) { try { sendRequestReply(Reply.CONNECTION_REFUSED, InetAddress.getByName("127.0.0.1"), 0, out); } catch (IOException ioe) {} - throw new SOCKSException("Error connecting (" - + e.getMessage() + ")"); + throw new SOCKSException("Error connecting", e); } catch (I2PException e) { try { sendRequestReply(Reply.CONNECTION_REFUSED, InetAddress.getByName("127.0.0.1"), 0, out); } catch (IOException ioe) {} - throw new SOCKSException("Error connecting (" - + e.getMessage() + ")"); + throw new SOCKSException("Error connecting", e); } return destSock; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java index f82ad339e1..7ae5997931 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java @@ -87,7 +87,7 @@ class SOCKS5Server extends SOCKSServer { if (manageRequest(in, out) == Command.UDP_ASSOCIATE) handleUDP(in, out); } catch (IOException e) { - throw new SOCKSException("Connection error: " + e); + throw new SOCKSException("Connection error", e); } setupCompleted = true; @@ -267,7 +267,7 @@ class SOCKS5Server extends SOCKSServer { sendRequestReply(Reply.SUCCEEDED, AddressType.IPV4, InetAddress.getByName("127.0.0.1"), null, 1, out); } catch (IOException e) { - throw new SOCKSException("Connection error: " + e); + throw new SOCKSException("Connection error", e); } } @@ -360,7 +360,7 @@ class SOCKS5Server extends SOCKSServer { try { out = new DataOutputStream(clientSock.getOutputStream()); } catch (IOException e) { - throw new SOCKSException("Connection error: " + e); + throw new SOCKSException("Connection error", e); } // FIXME: here we should read our config file, select an @@ -457,14 +457,14 @@ class SOCKS5Server extends SOCKSServer { try { sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out); } catch (IOException ioe) {} - throw new SOCKSException("Error connecting: " + e); + throw new SOCKSException("Connection error", e); } catch (I2PException e) { if (_log.shouldLog(Log.WARN)) _log.warn("socks error", e); try { sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out); } catch (IOException ioe) {} - throw new SOCKSException("Error connecting: " + e); + throw new SOCKSException("Connection error", e); } return destSock; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java index a9672295f8..a3bfd1c47c 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java @@ -73,7 +73,7 @@ class SOCKSServerFactory { } } catch (IOException e) { //_log.debug("error reading SOCKS protocol version"); - throw new SOCKSException("Connection error (" + e.getMessage() + ")"); + throw new SOCKSException("Connection error", e); } return serv;