diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java
index 7b182d105476d0c380aa81a5052673782367235a..92e78d3de270c0ca5b80338a2ee8af3da50f2003 100644
--- a/router/java/src/net/i2p/router/Shitlist.java
+++ b/router/java/src/net/i2p/router/Shitlist.java
@@ -198,6 +198,7 @@ public class Shitlist {
         if (transport == null) {
             // we hate the peer on *any* transport
             _context.netDb().fail(peer);
+            _context.tunnelManager().fail(peer);
         }
         //_context.tunnelManager().peerFailed(peer);
         //_context.messageRegistry().peerFailed(peer);
diff --git a/router/java/src/net/i2p/router/TunnelManagerFacade.java b/router/java/src/net/i2p/router/TunnelManagerFacade.java
index ae54f6077df59275f9c9a2c6294fda7b78af3f72..5e00d7010d60e615391f83d1ad543a8009ea2fe0 100644
--- a/router/java/src/net/i2p/router/TunnelManagerFacade.java
+++ b/router/java/src/net/i2p/router/TunnelManagerFacade.java
@@ -165,4 +165,7 @@ public interface TunnelManagerFacade extends Service {
     public TunnelPool getInboundExploratoryPool();
     /** for TunnelRenderer in router console */
     public TunnelPool getOutboundExploratoryPool();
+
+    /** @since 0.8.13 */
+    public void fail(Hash peer);
 }
diff --git a/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java b/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java
index b1574738cbb4c1aade3f0c26befc400639f098af..221f2d9e936b48a10364da6f12a53258af5d439b 100644
--- a/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java
+++ b/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java
@@ -70,4 +70,5 @@ public class DummyTunnelManagerFacade implements TunnelManagerFacade {
     public Map<Hash, TunnelPool> getOutboundClientPools() { return null; }
     public TunnelPool getInboundExploratoryPool() { return null; }
     public TunnelPool getOutboundExploratoryPool() { return null; }
+    public void fail(Hash peer) {}
 }
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
index c5397580f1842b5060d4bf74c60700787fddfae4..753f931bcb1bfa3640d508353aaf24a7c2cb485b 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java
@@ -486,8 +486,30 @@ public class TunnelPool {
         }
     }
 
-    /** This may be called multiple times from TestJob */
-    void tunnelFailed(PooledTunnelCreatorConfig cfg) {
+    /**
+     *  Remove the tunnel and blame all the peers (not necessarily equally).
+     *  This may be called multiple times from TestJob.
+     */
+    void tunnelFailed(TunnelInfo cfg) {
+        fail(cfg);
+        tellProfileFailed(cfg);
+    }
+
+    /**
+     *  Remove the tunnel and blame only one peer.
+     *  This may be called multiple times.
+     *
+     *  @since 0.8.13
+     */
+    void tunnelFailed(TunnelInfo cfg, Hash blamePeer) {
+        fail(cfg);
+        _context.profileManager().tunnelFailed(blamePeer, 100);
+    }
+
+    /**
+     *  Remove the tunnel.
+     */
+    private void fail(TunnelInfo cfg) {
         if (_log.shouldLog(Log.WARN))
             _log.warn(toString() + ": Tunnel failed: " + cfg);
         LeaseSet ls = null;
@@ -504,7 +526,6 @@ public class TunnelPool {
         }
         
         _manager.tunnelFailed();
-        tellProfileFailed(cfg);
         
         _lifetimeProcessed += cfg.getProcessedMessagesCount();
         updateRate();
@@ -516,9 +537,11 @@ public class TunnelPool {
         }
     }
 
-    // Blame all the other peers in the tunnel, with a probability
-    // inversely related to the tunnel length
-    private void tellProfileFailed(PooledTunnelCreatorConfig cfg) {
+    /**
+     *  Blame all the other peers in the tunnel, with a probability
+     *  inversely related to the tunnel length
+     */
+    private void tellProfileFailed(TunnelInfo cfg) {
         int len = cfg.getLength();
         if (len < 2)
             return;
@@ -543,7 +566,7 @@ public class TunnelPool {
         }
     }
 
-    void updateRate() {
+    private void updateRate() {
         long now = _context.clock().now();
         long et = now - _lastRateUpdate;
         if (et > 2*60*1000) {
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
index 8df88c8b0be821d0ff1b07808e30058dc51413a6..56f8a587bd4fbc276330c102c341fd75a9132b73 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
@@ -644,4 +644,57 @@ public class TunnelPoolManager implements TunnelManagerFacade {
     public TunnelPool getOutboundExploratoryPool() {
         return _outboundExploratory;
     }
+
+    /**
+     *  Fail all outbound tunnels with this peer as first hop,
+     *  and all inbound tunnels with this peer as the last hop,
+     *  baecause we can't contact it any more.
+     *  This is most likely to be triggered by an outbound tunnel.
+     *
+     *  @since 0.8.13
+     */
+    public void fail(Hash peer) {
+        if (_outboundExploratory != null)
+            failTunnelsWithFirstHop(_outboundExploratory, peer);
+        for (TunnelPool pool : _clientOutboundPools.values()) {
+            failTunnelsWithFirstHop(pool, peer);
+        }
+        if (_inboundExploratory != null)
+            failTunnelsWithLastHop(_inboundExploratory, peer);
+        for (TunnelPool pool : _clientInboundPools.values()) {
+            failTunnelsWithLastHop(pool, peer);
+        }
+    }
+
+    /**
+     *  Fail all (outbound) tunnels with this peer as first hop (not counting us)
+     *
+     *  @since 0.8.13
+     */
+    private void failTunnelsWithFirstHop(TunnelPool pool, Hash peer) {
+        for (TunnelInfo tun : pool.listTunnels()) {
+            int len = tun.getLength();
+            if (len > 1 && tun.getPeer(1).equals(peer)) {
+                if (_log.shouldLog(Log.WARN))
+                    _log.warn("Removing OB tunnel, first hop shitlisted: " + tun);
+                pool.tunnelFailed(tun, peer);
+            }
+        }
+    }
+
+    /**
+     *  Fail all (inbound) tunnels with this peer as last hop (not counting us)
+     *
+     *  @since 0.8.13
+     */
+    private void failTunnelsWithLastHop(TunnelPool pool, Hash peer) {
+        for (TunnelInfo tun : pool.listTunnels()) {
+            int len = tun.getLength();
+            if (len > 1 && tun.getPeer(len - 2).equals(peer)) {
+                if (_log.shouldLog(Log.WARN))
+                    _log.warn("Removing IB tunnel, prev. hop shitlisted: " + tun);
+                pool.tunnelFailed(tun, peer);
+            }
+        }
+    }
 }