diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index a07bb25de..487d86071 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -392,5 +392,34 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
   return m_executor.hard_fork_info(version);
 }
 
+bool t_command_parser_executor::show_bans(const std::vector<std::string>& args)
+{
+  if (!args.empty()) return false;
+  return m_executor.print_bans();
+}
+
+bool t_command_parser_executor::ban(const std::vector<std::string>& args)
+{
+  if (args.size() != 1 && args.size() != 2) return false;
+  std::string ip = args[0];
+  time_t seconds = P2P_IP_BLOCKTIME;
+  if (args.size() > 1)
+  {
+    seconds = std::stoi(args[0]);
+    if (seconds == 0)
+    {
+      return false;
+    }
+  }
+  return m_executor.ban(ip, seconds);
+}
+
+bool t_command_parser_executor::unban(const std::vector<std::string>& args)
+{
+  if (args.size() != 1) return false;
+  std::string ip = args[0];
+  return m_executor.unban(ip);
+}
+
 
 } // namespace daemonize
diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h
index f00fbd77e..0c042cd5d 100644
--- a/src/daemon/command_parser_executor.h
+++ b/src/daemon/command_parser_executor.h
@@ -106,6 +106,12 @@ public:
   bool stop_save_graph(const std::vector<std::string>& args);
   
   bool hard_fork_info(const std::vector<std::string>& args);
+
+  bool show_bans(const std::vector<std::string>& args);
+
+  bool ban(const std::vector<std::string>& args);
+
+  bool unban(const std::vector<std::string>& args);
 };
 
 } // namespace daemonize
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 8714b2569..0999ed30c 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -194,6 +194,21 @@ t_command_server::t_command_server(
     , std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1)
     , "Print hard fork voting information"
     );
+    m_command_lookup.set_handler(
+      "bans"
+    , std::bind(&t_command_parser_executor::show_bans, &m_parser, p::_1)
+    , "Show the currently banned IPs"
+    );
+    m_command_lookup.set_handler(
+      "ban"
+    , std::bind(&t_command_parser_executor::ban, &m_parser, p::_1)
+    , "Ban a given IP for a time"
+    );
+    m_command_lookup.set_handler(
+      "unban"
+    , std::bind(&t_command_parser_executor::unban, &m_parser, p::_1)
+    , "Unban a given IP"
+    );
 }
 
 bool t_command_server::process_command_str(const std::string& cmd)
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 176df81fc..547db1672 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -1036,4 +1036,110 @@ bool t_rpc_command_executor::hard_fork_info(uint8_t version)
     return true;
 }
 
+bool t_rpc_command_executor::print_bans()
+{
+    cryptonote::COMMAND_RPC_GETBANS::request req;
+    cryptonote::COMMAND_RPC_GETBANS::response res;
+    std::string fail_message = "Unsuccessful";
+    epee::json_rpc::error error_resp;
+
+    if (m_is_rpc)
+    {
+        if (!m_rpc_client->json_rpc_request(req, res, "get_bans", fail_message.c_str()))
+        {
+            return true;
+        }
+    }
+    else
+    {
+        if (!m_rpc_server->on_get_bans(req, res, error_resp))
+        {
+            tools::fail_msg_writer() << fail_message.c_str();
+            return true;
+        }
+    }
+
+    time_t now = time(nullptr);
+    for (auto i = res.bans.begin(); i != res.bans.end(); ++i)
+    {
+        time_t seconds = i->seconds - now;
+        tools::msg_writer() << epee::string_tools::get_ip_string_from_int32(i->ip) << " banned for " << seconds << " seconds";
+    }
+
+    return true;
+}
+
+
+bool t_rpc_command_executor::ban(const std::string &ip, time_t seconds)
+{
+    cryptonote::COMMAND_RPC_SETBANS::request req;
+    cryptonote::COMMAND_RPC_SETBANS::response res;
+    std::string fail_message = "Unsuccessful";
+    epee::json_rpc::error error_resp;
+
+    cryptonote::COMMAND_RPC_SETBANS::ban ban;
+    if (!epee::string_tools::get_ip_int32_from_string(ban.ip, ip))
+    {
+        tools::fail_msg_writer() << "Invalid IP";
+        return true;
+    }
+    ban.ban = true;
+    ban.seconds = seconds;
+    req.bans.push_back(ban);
+
+    if (m_is_rpc)
+    {
+        if (!m_rpc_client->json_rpc_request(req, res, "set_bans", fail_message.c_str()))
+        {
+            return true;
+        }
+    }
+    else
+    {
+        if (!m_rpc_server->on_set_bans(req, res, error_resp))
+        {
+            tools::fail_msg_writer() << fail_message.c_str();
+            return true;
+        }
+    }
+
+    return true;
+}
+
+bool t_rpc_command_executor::unban(const std::string &ip)
+{
+    cryptonote::COMMAND_RPC_SETBANS::request req;
+    cryptonote::COMMAND_RPC_SETBANS::response res;
+    std::string fail_message = "Unsuccessful";
+    epee::json_rpc::error error_resp;
+
+    cryptonote::COMMAND_RPC_SETBANS::ban ban;
+    if (!epee::string_tools::get_ip_int32_from_string(ban.ip, ip))
+    {
+        tools::fail_msg_writer() << "Invalid IP";
+        return true;
+    }
+    ban.ban = false;
+    ban.seconds = 0;
+    req.bans.push_back(ban);
+
+    if (m_is_rpc)
+    {
+        if (!m_rpc_client->json_rpc_request(req, res, "set_bans", fail_message.c_str()))
+        {
+            return true;
+        }
+    }
+    else
+    {
+        if (!m_rpc_server->on_set_bans(req, res, error_resp))
+        {
+            tools::fail_msg_writer() << fail_message.c_str();
+            return true;
+        }
+    }
+
+    return true;
+}
+
 }// namespace daemonize
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index 778b73acb..95c5624fa 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -124,6 +124,12 @@ public:
   bool stop_save_graph();
   
   bool hard_fork_info(uint8_t version);
+
+  bool print_bans();
+
+  bool ban(const std::string &ip, time_t seconds);
+
+  bool unban(const std::string &ip);
 };
 
 } // namespace daemonize
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 4aaac813e..39cbe01fa 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -117,6 +117,9 @@ namespace nodetool
     size_t get_outgoing_connections_count();
     peerlist_manager& get_peerlist_manager(){return m_peerlist;}
     void delete_connections(size_t count);
+    virtual bool block_ip(uint32_t adress, time_t seconds = P2P_IP_BLOCKTIME);
+    virtual bool unblock_ip(uint32_t address);
+    virtual std::map<uint32_t, time_t> get_blocked_ips() const { return m_blocked_ips; }
   private:
     const std::vector<std::string> m_seed_nodes_list =
     { "seeds.moneroseeds.se"
@@ -171,7 +174,6 @@ namespace nodetool
     virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
     virtual void request_callback(const epee::net_utils::connection_context_base& context);
     virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type)> f);
-    virtual bool block_ip(uint32_t adress);
     virtual bool add_ip_fail(uint32_t address);
     //----------------- i_connection_filter  --------------------------------------------------------
     virtual bool is_remote_ip_allowed(uint32_t adress);
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 11df7ee49..067f6378d 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -169,7 +169,7 @@ namespace nodetool
     auto it = m_blocked_ips.find(addr);
     if(it == m_blocked_ips.end())
       return true;
-    if(time(nullptr) - it->second > P2P_IP_BLOCKTIME )
+    if(time(nullptr) >= it->second)
     {
       m_blocked_ips.erase(it);
       LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << "is unblocked.", LOG_LEVEL_0);
@@ -186,15 +186,27 @@ namespace nodetool
   }
   //-----------------------------------------------------------------------------------
   template<class t_payload_net_handler>
-  bool node_server<t_payload_net_handler>::block_ip(uint32_t addr)
+  bool node_server<t_payload_net_handler>::block_ip(uint32_t addr, time_t seconds)
   {
     CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
-    m_blocked_ips[addr] = time(nullptr);
+    m_blocked_ips[addr] = time(nullptr) + seconds;
     LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << " blocked.", LOG_LEVEL_0);
     return true;
   }
   //-----------------------------------------------------------------------------------
   template<class t_payload_net_handler>
+  bool node_server<t_payload_net_handler>::unblock_ip(uint32_t addr)
+  {
+    CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
+    auto i = m_blocked_ips.find(addr);
+    if (i == m_blocked_ips.end())
+      return false;
+    m_blocked_ips.erase(i);
+    LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked.", LOG_LEVEL_0);
+    return true;
+  }
+  //-----------------------------------------------------------------------------------
+  template<class t_payload_net_handler>
   bool node_server<t_payload_net_handler>::add_ip_fail(uint32_t address)
   {
     CRITICAL_REGION_LOCAL(m_ip_fails_score_lock);
diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h
index 93b29deb2..2505006ad 100644
--- a/src/p2p/net_node_common.h
+++ b/src/p2p/net_node_common.h
@@ -50,7 +50,9 @@ namespace nodetool
     virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
     virtual uint64_t get_connections_count()=0;
     virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type)> f)=0;
-    virtual bool block_ip(uint32_t adress)=0;
+    virtual bool block_ip(uint32_t adress, time_t seconds = 0)=0;
+    virtual bool unblock_ip(uint32_t adress)=0;
+    virtual std::map<uint32_t, time_t> get_blocked_ips()const=0;
     virtual bool add_ip_fail(uint32_t adress)=0;
   };
 
@@ -86,10 +88,18 @@ namespace nodetool
     {
       return false;
     }
-    virtual bool block_ip(uint32_t adress)
+    virtual bool block_ip(uint32_t adress, time_t seconds)
     {
       return true;
     }
+    virtual bool unblock_ip(uint32_t adress)
+    {
+      return true;
+    }
+    virtual std::map<uint32_t, time_t> get_blocked_ips() const
+    {
+      return std::map<uint32_t, time_t>();
+    }
     virtual bool add_ip_fail(uint32_t adress)
     {
       return true;
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index f5e700033..e2b30b6e0 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -899,6 +899,49 @@ namespace cryptonote
 #endif
   }
   //------------------------------------------------------------------------------------------------------------------------------
+  bool core_rpc_server::on_get_bans(const COMMAND_RPC_GETBANS::request& req, COMMAND_RPC_GETBANS::response& res, epee::json_rpc::error& error_resp)
+  {
+    if(!check_core_busy())
+    {
+      error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+      error_resp.message = "Core is busy.";
+      return false;
+    }
+
+    std::map<uint32_t, time_t> blocked_ips = m_p2p.get_blocked_ips();
+    for (std::map<uint32_t, time_t>::const_iterator i = blocked_ips.begin(); i != blocked_ips.end(); ++i)
+    {
+      COMMAND_RPC_GETBANS::ban b;
+      b.ip = i->first;
+      b.seconds = i->second;
+      res.bans.push_back(b);
+    }
+
+    res.status = CORE_RPC_STATUS_OK;
+    return true;
+  }
+  //------------------------------------------------------------------------------------------------------------------------------
+  bool core_rpc_server::on_set_bans(const COMMAND_RPC_SETBANS::request& req, COMMAND_RPC_SETBANS::response& res, epee::json_rpc::error& error_resp)
+  {
+    if(!check_core_busy())
+    {
+      error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+      error_resp.message = "Core is busy.";
+      return false;
+    }
+
+    for (auto i = req.bans.begin(); i != req.bans.end(); ++i)
+    {
+      if (i->ban)
+        m_p2p.block_ip(i->ip, i->seconds);
+      else
+        m_p2p.unblock_ip(i->ip);
+    }
+
+    res.status = CORE_RPC_STATUS_OK;
+    return true;
+  }
+  //------------------------------------------------------------------------------------------------------------------------------
   bool core_rpc_server::on_fast_exit(const COMMAND_RPC_FAST_EXIT::request& req, COMMAND_RPC_FAST_EXIT::response& res)
   {
 	  cryptonote::core::set_fast_exit();
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 1fbd0981f..3c230fd82 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -105,6 +105,8 @@ namespace cryptonote
         MAP_JON_RPC_WE("get_connections",        on_get_connections,            COMMAND_RPC_GET_CONNECTIONS)
         MAP_JON_RPC_WE("get_info",               on_get_info_json,              COMMAND_RPC_GET_INFO)
         MAP_JON_RPC_WE("hard_fork_info",         on_hard_fork_info,             COMMAND_RPC_HARD_FORK_INFO)
+        MAP_JON_RPC_WE("setbans",                on_set_bans,                   COMMAND_RPC_SETBANS)
+        MAP_JON_RPC_WE("getbans",                on_get_bans,                   COMMAND_RPC_GETBANS)
       END_JSON_RPC_MAP()
     END_URI_MAP2()
 
@@ -142,6 +144,8 @@ namespace cryptonote
     bool on_get_connections(const COMMAND_RPC_GET_CONNECTIONS::request& req, COMMAND_RPC_GET_CONNECTIONS::response& res, epee::json_rpc::error& error_resp);
     bool on_get_info_json(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, epee::json_rpc::error& error_resp);
     bool on_hard_fork_info(const COMMAND_RPC_HARD_FORK_INFO::request& req, COMMAND_RPC_HARD_FORK_INFO::response& res, epee::json_rpc::error& error_resp);
+    bool on_set_bans(const COMMAND_RPC_SETBANS::request& req, COMMAND_RPC_SETBANS::response& res, epee::json_rpc::error& error_resp);
+    bool on_get_bans(const COMMAND_RPC_GETBANS::request& req, COMMAND_RPC_GETBANS::response& res, epee::json_rpc::error& error_resp);
     //-----------------------
 
 private:
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index aa88ffcb4..7fb5c46fc 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -888,5 +888,70 @@ namespace cryptonote
       END_KV_SERIALIZE_MAP()
     };
   };
+
+  struct COMMAND_RPC_GETBANS
+  {
+    struct ban
+    {
+      uint32_t ip;
+      uint32_t seconds;
+
+      BEGIN_KV_SERIALIZE_MAP()
+        KV_SERIALIZE(ip)
+        KV_SERIALIZE(seconds)
+      END_KV_SERIALIZE_MAP()
+    };
+
+    struct request
+    {
+      BEGIN_KV_SERIALIZE_MAP()
+      END_KV_SERIALIZE_MAP()
+    };
+
+    struct response
+    {
+      std::string status;
+      std::vector<ban> bans;
+
+      BEGIN_KV_SERIALIZE_MAP()
+        KV_SERIALIZE(status)
+        KV_SERIALIZE(bans)
+      END_KV_SERIALIZE_MAP()
+    };
+  };
+
+  struct COMMAND_RPC_SETBANS
+  {
+    struct ban
+    {
+      uint32_t ip;
+      bool ban;
+      uint32_t seconds;
+
+      BEGIN_KV_SERIALIZE_MAP()
+        KV_SERIALIZE(ip)
+        KV_SERIALIZE(ban)
+        KV_SERIALIZE(seconds)
+      END_KV_SERIALIZE_MAP()
+    };
+
+    struct request
+    {
+      std::vector<ban> bans;
+
+      BEGIN_KV_SERIALIZE_MAP()
+        KV_SERIALIZE(bans)
+      END_KV_SERIALIZE_MAP()
+    };
+
+    struct response
+    {
+      std::string status;
+
+      BEGIN_KV_SERIALIZE_MAP()
+        KV_SERIALIZE(status)
+      END_KV_SERIALIZE_MAP()
+    };
+  };
 }