diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
index 560475e42f65999877b418ea3939220820aaf4fa..3b279a679aa008448a4170d8ce4f6b422840477c 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
@@ -662,7 +662,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
      * "openSOCKSTunnelResult" = "ok" or "error" after the client tunnel has
      * started.
      *
-     * @param args {portNumber}
+     * @param args {portNumber [, sharedClient]}
      * @param l logger to receive events and output
      */
     public void runSOCKSTunnel(String args[], Logging l) {
@@ -677,6 +677,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
                 return;
             }
 
+            boolean isShared = false;
+            if (args.length > 1)
+                isShared = "true".equalsIgnoreCase(args[1].trim());
+
+            ownDest = !isShared;
             I2PTunnelTask task;
             task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
             addtask(task);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
index 955d3abd1e82afb47427608c7176579a7a608ea5..f8592fcd39586e2e61a9947f05c030e7cdd26c92 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
@@ -135,8 +135,10 @@ public class TunnelController implements Logging {
         }
         if ("httpclient".equals(type)) {
             startHttpClient();
-        }else if("ircclient".equals(type)) {
+        } else if("ircclient".equals(type)) {
             startIrcClient();
+        } else if("sockstunnel".equals(type)) {
+            startSocksClient();
         } else if ("client".equals(type)) {
             startClient();
         } else if ("server".equals(type)) {
@@ -176,6 +178,17 @@ public class TunnelController implements Logging {
         _running = true;
     }
     
+    private void startSocksClient() {
+        setI2CPOptions();
+        setSessionOptions();
+        setListenOn();
+        String listenPort = getListenPort();
+        String sharedClient = getSharedClient();
+        _tunnel.runSOCKSTunnel(new String[] { listenPort, sharedClient }, this);
+        acquire();
+        _running = true;
+    }
+    
     /** 
      * Note the fact that we are using some sessions, so that they dont get
      * closed by some other tunnels
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 357149652e54fc3b0936727347d5ba0fec5133a4..b9b04c57ac2b585069582450402bb84f49759bfb 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java
@@ -39,8 +39,7 @@ public class SOCKSServerFactory {
                 serv = new SOCKS5Server(s);
                 break;
             default:
-                _log.debug("SOCKS protocol version not supported (" + Integer.toHexString(socksVer) + ")");
-                return null;
+                throw new SOCKSException("SOCKS protocol version not supported (" + Integer.toHexString(socksVer) + ")");
             }
         } catch (IOException e) {
             _log.debug("error reading SOCKS protocol version");
@@ -49,4 +48,4 @@ public class SOCKSServerFactory {
 
         return serv;
     }
-}
\ No newline at end of file
+}
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
index 06a46b7012c6c9cc3103ee53008eb87173a0ddb0..07730718adeab926e743fe539020bbe87e02dfc8 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
@@ -31,9 +31,7 @@ public class EditBean extends IndexBean {
         if (controllers.size() > tunnel) {
             TunnelController cur = (TunnelController)controllers.get(tunnel);
             if (cur == null) return false;
-            return ( ("client".equals(cur.getType())) || 
-            		 ("httpclient".equals(cur.getType()))||
-            		 ("ircclient".equals(cur.getType())));
+            return isClient(cur.getType());
         } else {
             return false;
         }
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
index 8c361195add42d262599b83dd731901b95c13538..1500150e3e6e4b6882f714f2b50b05072e71dc78 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
@@ -209,10 +209,7 @@ public class IndexBean {
         }
         // Only modify other shared tunnels
         // if the current tunnel is shared, and of supported type
-        if ("true".equalsIgnoreCase(cur.getSharedClient()) &&
-            ("ircclient".equals(cur.getType()) ||
-             "httpclient".equals(cur.getType()) ||
-             "client".equals(cur.getType()))) {
+        if ("true".equalsIgnoreCase(cur.getSharedClient()) && isClient(cur.getType())) {
             // all clients use the same I2CP session, and as such, use the same I2CP options
             List controllers = _group.getControllers();
 
@@ -224,11 +221,7 @@ public class IndexBean {
 
                 // Only modify this non-current tunnel
                 // if it belongs to a shared destination, and is of supported type
-                if ("true".equalsIgnoreCase(c.getSharedClient()) &&
-                    ("httpclient".equals(c.getType()) ||
-                     "ircclient".equals(c.getType()) ||
-                     "client".equals(c.getType()))) {
-
+                if ("true".equalsIgnoreCase(c.getSharedClient()) && isClient(c.getType())) {
                     Properties cOpt = c.getConfig("");
                     if (_tunnelQuantity != null) {
                         cOpt.setProperty("option.inbound.quantity", _tunnelQuantity);
@@ -326,9 +319,14 @@ public class IndexBean {
     public boolean isClient(int tunnelNum) {
         TunnelController cur = getController(tunnelNum);
         if (cur == null) return false;
-        return ( ("client".equals(cur.getType())) || 
-        		("httpclient".equals(cur.getType())) ||
-        		("ircclient".equals(cur.getType())));
+        return isClient(cur.getType());
+    }
+
+    public static boolean isClient(String type) {
+        return ( ("client".equals(type)) || 
+        		("httpclient".equals(type)) ||
+        		("sockstunnel".equals(type)) ||
+        		("ircclient".equals(type)));
     }
     
     public String getTunnelName(int tunnel) {
@@ -361,6 +359,7 @@ public class IndexBean {
         else if ("ircclient".equals(internalType)) return "IRC client";
         else if ("server".equals(internalType)) return "Standard server";
         else if ("httpserver".equals(internalType)) return "HTTP server";
+        else if ("sockstunnel".equals(internalType)) return "SOCKS proxy";
         else return internalType;
     }
     
@@ -579,77 +578,40 @@ public class IndexBean {
         Properties config = new Properties();
         updateConfigGeneric(config);
         
-        if ("httpclient".equals(_type)) {
+        if (isClient(_type)) {
+            // generic client stuff
             if (_port != null)
                 config.setProperty("listenPort", _port);
             if (_reachableByOther != null)
                 config.setProperty("interface", _reachableByOther);
             else
                 config.setProperty("interface", _reachableBy);
-            if (_proxyList != null)
-                config.setProperty("proxyList", _proxyList);
-
-        	config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
-        	config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
+            config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
+            config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
             if (_name != null && !_sharedClient) {
                  config.setProperty("option.inbound.nickname", _name);
                  config.setProperty("option.outbound.nickname", _name);
             }
-
             config.setProperty("sharedClient", _sharedClient + "");
-        }else if ("ircclient".equals(_type)) {
-                if (_port != null)
-                    config.setProperty("listenPort", _port);
-                if (_reachableByOther != null)
-                    config.setProperty("interface", _reachableByOther);
-                else
-                    config.setProperty("interface", _reachableBy);
-                if (_targetDestination != null)
-                    config.setProperty("targetDestination", _targetDestination);
-
-            	config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
-            	config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
-                if (_name != null && !_sharedClient) {
-                     config.setProperty("option.inbound.nickname", _name);
-                     config.setProperty("option.outbound.nickname", _name);
-                }
-
-                config.setProperty("sharedClient", _sharedClient + "");
-        } else if ("client".equals(_type)) {
-            if (_port != null)
-                config.setProperty("listenPort", _port);
-            if (_reachableByOther != null)
-                config.setProperty("interface", _reachableByOther);
-            else
-                config.setProperty("interface", _reachableBy);
-            if (_targetDestination != null)
-                config.setProperty("targetDestination", _targetDestination);
-            
-            config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
-            config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
-            if (_name != null && !_sharedClient) {
-                config.setProperty("option.inbound.nickname", _name);
-                config.setProperty("option.outbound.nickname", _name);
-           }
-            config.setProperty("sharedClient", _sharedClient + "");
-        } else if ("server".equals(_type)) {
+        } else {
+            // generic server stuff
             if (_targetHost != null)
                 config.setProperty("targetHost", _targetHost);
             if (_targetPort != null)
                 config.setProperty("targetPort", _targetPort);
             if (_privKeyFile != null)
                 config.setProperty("privKeyFile", _privKeyFile);
+        }
+
+        if ("httpclient".equals(_type)) {
+            if (_proxyList != null)
+                config.setProperty("proxyList", _proxyList);
+        } else if ("ircclient".equals(_type) || "client".equals(_type)) {
+            if (_targetDestination != null)
+                config.setProperty("targetDestination", _targetDestination);
         } else if ("httpserver".equals(_type)) {
-            if (_targetHost != null)
-                config.setProperty("targetHost", _targetHost);
-            if (_targetPort != null)
-                config.setProperty("targetPort", _targetPort);
-            if (_privKeyFile != null)
-                config.setProperty("privKeyFile", _privKeyFile);
             if (_spoofedHost != null)
                 config.setProperty("spoofedHost", _spoofedHost);
-        } else {
-            return null;
         }
 
         return config;
diff --git a/apps/i2ptunnel/jsp/edit.jsp b/apps/i2ptunnel/jsp/edit.jsp
index 931629fb1f325479ccc820c17987de59757cbe3c..67fdf016c37daf170f4b92db3851cc5df898dd8d 100644
--- a/apps/i2ptunnel/jsp/edit.jsp
+++ b/apps/i2ptunnel/jsp/edit.jsp
@@ -14,7 +14,7 @@ String tun = request.getParameter("tunnel");
 } else {
   String type = request.getParameter("type");
   int curTunnel = -1;
-  if ("client".equals(type) || "httpclient".equals(type) || "ircclient".equals(type)) {
+  if (EditBean.isClient(type)) {
     %><jsp:include page="editClient.jsp" /><%
   } else if ("server".equals(type) || "httpserver".equals(type)) {
     %><jsp:include page="editServer.jsp" /><%
@@ -22,4 +22,4 @@ String tun = request.getParameter("tunnel");
     %>Invalid tunnel type<%
   }
 }
-%>
\ No newline at end of file
+%>
diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp
index 2f06e1779cf2f19b5727a231ac16a540c4613d65..f7ee2294c73726ad36296251b225c7c1061fb89e 100644
--- a/apps/i2ptunnel/jsp/editClient.jsp
+++ b/apps/i2ptunnel/jsp/editClient.jsp
@@ -116,14 +116,14 @@
                 <hr />
             </div>
            
-            <% if ("httpclient".equals(editBean.getInternalType(curTunnel))) {
+            <% if ("httpclient".equals(tunnelType)) {
           %><div id="destinationField" class="rowItem">
                 <label for="proxyList" accesskey="x">
                     Outpro<span class="accessKey">x</span>ies:
                 </label>
                 <input type="text" size="30" id="proxyList" name="proxyList" title="List of Outproxy I2P destinations" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />                
             </div>
-            <% } else {
+            <% } else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) {
           %><div id="destinationField" class="rowItem">
                 <label for="targetDestination" accesskey="T">
                     <span class="accessKey">T</span>unnel Destination:
@@ -205,7 +205,7 @@
                     <span class="accessKey">V</span>ariance:
                 </label>
                 <select id="tunnelVariance" name="tunnelVariance" title="Level of Randomization for Tunnel Depth" class="selectbox">
-                    <% int tunnelVariance = editBean.getTunnelVariance(curTunnel, -1);
+                    <% int tunnelVariance = editBean.getTunnelVariance(curTunnel, 0);
                   %><option value="0"<%=(tunnelVariance  ==  0 ? " selected=\"selected\"" : "") %>>0 hop variance (no randomisation, consistant performance)</option>
                     <option value="1"<%=(tunnelVariance  ==  1 ? " selected=\"selected\"" : "") %>>+ 0-1 hop variance (medium additive randomisation, subtractive performance)</option>
                     <option value="2"<%=(tunnelVariance  ==  2 ? " selected=\"selected\"" : "") %>>+ 0-2 hop variance (high additive randomisation, subtractive performance)</option>
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 9fc2d2a9677a116be38433e2f4292751b3c4a398..0825493073c731d37d6b568fc6609e9258f21986 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -112,10 +112,12 @@
             }
       %></div>
 
+      <% if (!"sockstunnel".equals(indexBean.getInternalType(curClient))) { %>
         <div class="destinationField rowItem">
             <label>Destination:</label>
             <input class="freetext" size="40" readonly="readonly" value="<%=indexBean.getClientDestination(curClient)%>" />
         </div>
+      <% } %>
 
         <div class="descriptionField rowItem">
             <label>Description:</label>
@@ -140,6 +142,7 @@
                         <option value="client">Standard</option>
                         <option value="httpclient">HTTP</option>
                         <option value="ircclient">IRC</option>
+                        <option value="sockstunnel">SOCKS</option>
                     </select>
                     <input class="control" type="submit" value="Create" />
                 </div>