diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java
index ce1b67a6cd492cae68615f544c72170a48c3b70b..26ef4d68e2e8b0f12f3e4dba2ed3cd2fe0c15e50 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java
@@ -277,7 +277,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
             setEntry(headers, "Accept-encoding", ""); 
 
             socket.setReadTimeout(readTimeout);
-            Socket s = getSocket(socket.getLocalPort());
+            Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
             long afterSocket = getTunnel().getContext().clock().now();
             // instead of i2ptunnelrunner, use something that reads the HTTP 
             // request from the socket, modifies the headers, sends the request to the 
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
index b50f7185e0596cd21a6f524a6a5cc85ac3841421..5cd691a3f3e081b1f5a0c0752759915f3541b48d 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
@@ -137,7 +137,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
 				buf.append("\r\n");
 				modifiedRegistration = buf.toString();
 			}
-            Socket s = getSocket(socket.getLocalPort());
+            Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
             new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
         } catch (SocketException ex) {
             try {
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
index 5daa64935fc58ceb9438e4e5246178934f511fdd..e79bf7ce456a62d2dd34a03340a33eeda24135c0 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
@@ -11,6 +11,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.ConnectException;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.SocketException;
@@ -33,6 +34,7 @@ import net.i2p.client.streaming.I2PSocket;
 import net.i2p.client.streaming.I2PSocketManager;
 import net.i2p.client.streaming.I2PSocketManagerFactory;
 import net.i2p.data.Base64;
+import net.i2p.data.Hash;
 import net.i2p.util.EventDispatcher;
 import net.i2p.util.I2PAppThread;
 import net.i2p.util.I2PSSLSocketFactory;
@@ -62,6 +64,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
     private static final String PROP_USE_POOL = "i2ptunnel.usePool";
     private static final boolean DEFAULT_USE_POOL = true;
     public static final String PROP_USE_SSL = "useSSL";
+    public static final String PROP_UNIQUE_LOCAL = "enableUniqueLocal";
     /** apparently unused */
     protected static volatile long __serverId = 0;
     /** max number of threads  - this many slowlorisses will DOS this server, but too high could OOM the JVM */
@@ -518,7 +521,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
         //threads.
         try {
             socket.setReadTimeout(readTimeout);
-            Socket s = getSocket(socket.getLocalPort());
+            Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
             afterSocket = getTunnel().getContext().clock().now();
             new I2PTunnelRunner(s, socket, slock, null, null);
 
@@ -543,9 +546,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
      *  To configure a specific host:port as the server for incoming port xx,
      *  set option targetForPort.xx=host:port
      *
+     *  @param from may be used to construct local address since 0.9.13
      *  @since 0.9.9
      */
-    protected Socket getSocket(int incomingPort) throws IOException {
+    protected Socket getSocket(Hash from, int incomingPort) throws IOException {
         InetAddress host = remoteHost;
         int port = remotePort;
         if (incomingPort != 0 && !_socketMap.isEmpty()) {
@@ -557,16 +561,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
                 port = isa.getPort();
             }
         }
-        return getSocket(host, port);
+        return getSocket(from, host, port);
     }
 
     /**
      *  Get a regular or SSL socket depending on config.
      *  The SSL config applies to all hosts/ports.
      *
+     *  @param from may be used to construct local address since 0.9.13
      *  @since 0.9.9
      */
-    protected Socket getSocket(InetAddress remoteHost, int remotePort) throws IOException {
+    protected Socket getSocket(Hash from, InetAddress remoteHost, int remotePort) throws IOException {
         String opt = getTunnel().getClientOptions().getProperty(PROP_USE_SSL);
         if (Boolean.parseBoolean(opt)) {
             synchronized(sslLock) {
@@ -583,7 +588,26 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
             }
             return _sslFactory.createSocket(remoteHost, remotePort);
         } else {
-            return new Socket(remoteHost, remotePort);
+            // as suggested in https://lists.torproject.org/pipermail/tor-dev/2014-March/006576.html
+            boolean unique = Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_UNIQUE_LOCAL));
+            if (unique && remoteHost.isLoopbackAddress()) {
+                byte[] addr;
+                if (remoteHost instanceof Inet4Address) {
+                    addr = new byte[4];
+                    addr[0] = 127;
+                    System.arraycopy(from.getData(), 0, addr, 1, 3);
+                } else {
+                    addr = new byte[16];
+                    addr[0] = (byte) 0xfd;
+                    System.arraycopy(from.getData(), 0, addr, 1, 15);
+                }
+                InetAddress local = InetAddress.getByAddress(addr);
+                // Javadocs say local port of 0 allowed in Java 7.
+                // Not clear if supported in Java 6 or not.
+                return new Socket(remoteHost, remotePort, local, 0);
+            } else {
+                return new Socket(remoteHost, remotePort);
+            }
         }
     }
 }
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 2f5152ad1f160d9e2e40d0bcbe6b92cd1b7e7f57..1abc56c98d910c3d403ab409bb7185e778817e26 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
@@ -25,6 +25,7 @@ import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
 import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
 import net.i2p.i2ptunnel.I2PTunnelHTTPServer;
 import net.i2p.i2ptunnel.I2PTunnelIRCClient;
+import net.i2p.i2ptunnel.I2PTunnelServer;
 import net.i2p.i2ptunnel.TunnelController;
 import net.i2p.i2ptunnel.TunnelControllerGroup;
 import net.i2p.util.Addresses;
@@ -324,6 +325,11 @@ public class EditBean extends IndexBean {
     public int getPostTotalBanTime(int tunnel) {
         return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60;
     }
+    
+    /** @since 0.9.13 */
+    public boolean getUniqueLocal(int tunnel) {
+        return getBooleanProperty(tunnel, I2PTunnelServer.PROP_UNIQUE_LOCAL);
+    }
 
     private int getProperty(int tunnel, String prop, int def) {
         TunnelController tun = getController(tunnel);
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 d69080592c13a43678bedc9d50a8a7ad3a146f5f..d275d385ce14a3a83cdf70b46faaabe361f20277 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
@@ -823,6 +823,11 @@ public class IndexBean {
         return false;
     }
 
+    /** @since 0.9.13 */
+    public void setUniqueLocal(String moo) {
+        _booleanOptions.add(I2PTunnelServer.PROP_UNIQUE_LOCAL);
+    }
+
     protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
     protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
 
@@ -1259,7 +1264,8 @@ public class IndexBean {
     private static final String _booleanServerOpts[] = {
         "i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST,
         I2PTunnelServer.PROP_USE_SSL,
-        I2PTunnelHTTPServer.OPT_REJECT_INPROXY
+        I2PTunnelHTTPServer.OPT_REJECT_INPROXY,
+        I2PTunnelServer.PROP_UNIQUE_LOCAL
         };
     private static final String _otherClientOpts[] = {
         "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp
index 6a39b7a4af1747d4af21b9a47aeca602a0c49a94..4dba5773f7d45b2b3e958adb8ae335baa378d9fa 100644
--- a/apps/i2ptunnel/jsp/editServer.jsp
+++ b/apps/i2ptunnel/jsp/editServer.jsp
@@ -206,9 +206,15 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
                     <%=intl._("Local destination")%>(<span class="accessKey">L</span>):
                 </label>
                 <textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off" spellcheck="false"><%=editBean.getDestinationBase64(curTunnel)%></textarea>               
-         <% if (!"".equals(editBean.getDestinationBase64(curTunnel))) { %>    
-            <a href="/susidns/addressbook.jsp?book=private&amp;hostname=<%=editBean.getTunnelName(curTunnel)%>&amp;destination=<%=editBean.getDestinationBase64(curTunnel)%>#add"><%=intl._("Add to local addressbook")%></a>    
-         <% } %>
+         <% String b64 = editBean.getDestinationBase64(curTunnel);
+            if (!"".equals(b64)) {
+                String name = editBean.getSpoofedHost(curTunnel);
+                if (name == null || name.equals(""))
+                    name = editBean.getTunnelName(curTunnel);
+                if (!"".equals(name)) { %>
+                    <a href="/susidns/addressbook.jsp?book=private&amp;hostname=<%=name%>&amp;destination=<%=b64%>#add"><%=intl._("Add to local addressbook")%></a>    
+         <%     }
+            } %>
             </div>
 
             <% if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
@@ -396,7 +402,20 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
                 </div>
               </div>
             <% } // httpserver
-            %><div class="subdivider">
+            %><div class="rowItem">
+                <div id="optionsField" class="rowItem">
+                    <label>
+                        <%=intl._("Unique Local Address per Client")%>:
+                    </label>
+                </div>
+                <div id="portField" class="rowItem">
+                    <label for="access" accesskey="d">
+                        <%=intl._("Enable")%>:
+                    </label>
+                    <input value="1" type="checkbox" id="startOnLoad" name="uniqueLocal" title="Use unique IP addresses for each connecting client (local non-SSL servers only)"<%=(editBean.getUniqueLocal(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />                
+                </div>
+            </div>
+            <div class="subdivider">
                 <hr />
             </div>