added port filter for outgoing connections
This commit is contained in:
parent
aea4e503c5
commit
d0412a2244
|
@ -224,6 +224,7 @@ namespace libtorrent
|
||||||
bool is_aborted() const { return m_abort; }
|
bool is_aborted() const { return m_abort; }
|
||||||
|
|
||||||
void set_ip_filter(ip_filter const& f);
|
void set_ip_filter(ip_filter const& f);
|
||||||
|
void set_port_filter(port_filter const& f);
|
||||||
|
|
||||||
bool listen_on(
|
bool listen_on(
|
||||||
std::pair<int, int> const& port_range
|
std::pair<int, int> const& port_range
|
||||||
|
@ -351,6 +352,9 @@ namespace libtorrent
|
||||||
|
|
||||||
// filters incoming connections
|
// filters incoming connections
|
||||||
ip_filter m_ip_filter;
|
ip_filter m_ip_filter;
|
||||||
|
|
||||||
|
// filters outgoing connections
|
||||||
|
port_filter m_port_filter;
|
||||||
|
|
||||||
// the peer id that is generated at the start of the session
|
// the peer id that is generated at the start of the session
|
||||||
peer_id m_peer_id;
|
peer_id m_peer_id;
|
||||||
|
|
|
@ -71,20 +71,82 @@ struct ip_range
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template<class Addr>
|
||||||
|
Addr zero()
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type zero;
|
||||||
|
std::fill(zero.begin(), zero.end(), 0);
|
||||||
|
return Addr(zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline boost::uint16_t zero<boost::uint16_t>() { return 0; }
|
||||||
|
|
||||||
|
template<class Addr>
|
||||||
|
Addr plus_one(Addr const& a)
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp(a.to_bytes());
|
||||||
|
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||||
|
for (iter i = tmp.rbegin()
|
||||||
|
, end(tmp.rend()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (*i < (std::numeric_limits<typename iter::value_type>::max)())
|
||||||
|
{
|
||||||
|
*i += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*i = 0;
|
||||||
|
}
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
|
||||||
|
|
||||||
|
template<class Addr>
|
||||||
|
Addr minus_one(Addr const& a)
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp(a.to_bytes());
|
||||||
|
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||||
|
for (iter i = tmp.rbegin()
|
||||||
|
, end(tmp.rend()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (*i > 0)
|
||||||
|
{
|
||||||
|
*i -= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*i = (std::numeric_limits<typename iter::value_type>::max)();
|
||||||
|
}
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
|
||||||
|
|
||||||
|
template<class Addr>
|
||||||
|
Addr max_addr()
|
||||||
|
{
|
||||||
|
typename Addr::bytes_type tmp;
|
||||||
|
std::fill(tmp.begin(), tmp.end()
|
||||||
|
, (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
|
||||||
|
return Addr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline boost::uint16_t max_addr<boost::uint16_t>()
|
||||||
|
{ return std::numeric_limits<boost::uint16_t>::max(); }
|
||||||
|
|
||||||
// this is the generic implementation of
|
// this is the generic implementation of
|
||||||
// a filter for a specific address type.
|
// a filter for a specific address type.
|
||||||
// it works with IPv4 and IPv6
|
// it works with IPv4 and IPv6
|
||||||
template<class Addr>
|
template<class Addr>
|
||||||
class TORRENT_EXPORT filter_impl
|
class filter_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
filter_impl()
|
filter_impl()
|
||||||
{
|
{
|
||||||
typename Addr::bytes_type zero;
|
|
||||||
std::fill(zero.begin(), zero.end(), 0);
|
|
||||||
// make the entire ip-range non-blocked
|
// make the entire ip-range non-blocked
|
||||||
m_access_list.insert(range(Addr(zero), 0));
|
m_access_list.insert(range(zero<Addr>(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_rule(Addr first, Addr last, int flags)
|
void add_rule(Addr first, Addr last, int flags)
|
||||||
|
@ -134,7 +196,7 @@ namespace detail
|
||||||
if ((j != m_access_list.end()
|
if ((j != m_access_list.end()
|
||||||
&& minus_one(j->start) != last)
|
&& minus_one(j->start) != last)
|
||||||
|| (j == m_access_list.end()
|
|| (j == m_access_list.end()
|
||||||
&& last != max_addr()))
|
&& last != max_addr<Addr>()))
|
||||||
{
|
{
|
||||||
assert(j == m_access_list.end() || last < minus_one(j->start));
|
assert(j == m_access_list.end() || last < minus_one(j->start));
|
||||||
if (last_access != flags)
|
if (last_access != flags)
|
||||||
|
@ -170,7 +232,7 @@ namespace detail
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
if (i == end)
|
if (i == end)
|
||||||
r.last = max_addr();
|
r.last = max_addr<Addr>();
|
||||||
else
|
else
|
||||||
r.last = minus_one(i->start);
|
r.last = minus_one(i->start);
|
||||||
|
|
||||||
|
@ -181,48 +243,6 @@ namespace detail
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Addr plus_one(Addr const& a) const
|
|
||||||
{
|
|
||||||
typename Addr::bytes_type tmp(a.to_bytes());
|
|
||||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
|
||||||
for (iter i = tmp.rbegin()
|
|
||||||
, end(tmp.rend()); i != end; ++i)
|
|
||||||
{
|
|
||||||
if (*i < (std::numeric_limits<typename iter::value_type>::max)())
|
|
||||||
{
|
|
||||||
*i += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*i = 0;
|
|
||||||
}
|
|
||||||
return Addr(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr minus_one(Addr const& a) const
|
|
||||||
{
|
|
||||||
typename Addr::bytes_type tmp(a.to_bytes());
|
|
||||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
|
||||||
for (iter i = tmp.rbegin()
|
|
||||||
, end(tmp.rend()); i != end; ++i)
|
|
||||||
{
|
|
||||||
if (*i > 0)
|
|
||||||
{
|
|
||||||
*i -= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*i = (std::numeric_limits<typename iter::value_type>::max)();
|
|
||||||
}
|
|
||||||
return Addr(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr max_addr() const
|
|
||||||
{
|
|
||||||
typename Addr::bytes_type tmp;
|
|
||||||
std::fill(tmp.begin(), tmp.end()
|
|
||||||
, (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
|
|
||||||
return Addr(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct range
|
struct range
|
||||||
{
|
{
|
||||||
range(Addr addr, int access = 0): start(addr), access(access) {}
|
range(Addr addr, int access = 0): start(addr), access(access) {}
|
||||||
|
@ -270,6 +290,24 @@ private:
|
||||||
detail::filter_impl<address_v6> m_filter6;
|
detail::filter_impl<address_v6> m_filter6;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TORRENT_EXPORT port_filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum access_flags
|
||||||
|
{
|
||||||
|
blocked = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
void add_rule(boost::uint16_t first, boost::uint16_t last, int flags);
|
||||||
|
int access(boost::uint16_t port) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
detail::filter_impl<boost::uint16_t> m_filter;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,6 +72,7 @@ namespace libtorrent
|
||||||
struct torrent_plugin;
|
struct torrent_plugin;
|
||||||
class torrent;
|
class torrent;
|
||||||
class ip_filter;
|
class ip_filter;
|
||||||
|
class port_filter;
|
||||||
class connection_queue;
|
class connection_queue;
|
||||||
|
|
||||||
namespace aux
|
namespace aux
|
||||||
|
@ -182,6 +183,7 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_ip_filter(ip_filter const& f);
|
void set_ip_filter(ip_filter const& f);
|
||||||
|
void set_port_filter(port_filter const& f);
|
||||||
void set_peer_id(peer_id const& pid);
|
void set_peer_id(peer_id const& pid);
|
||||||
void set_key(int key);
|
void set_key(int key);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,15 @@ namespace libtorrent
|
||||||
, m_filter6.export_filter());
|
, m_filter6.export_filter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void port_filter::add_rule(boost::uint16_t first, boost::uint16_t last, int flags)
|
||||||
|
{
|
||||||
|
m_filter.add_rule(first, last, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int port_filter::access(boost::uint16_t port) const
|
||||||
|
{
|
||||||
|
return m_filter.access(port);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
void ip_filter::print() const
|
void ip_filter::print() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -524,6 +524,8 @@ namespace libtorrent
|
||||||
int max_failcount = m_torrent->settings().max_failcount;
|
int max_failcount = m_torrent->settings().max_failcount;
|
||||||
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
||||||
|
|
||||||
|
aux::session_impl& ses = m_torrent->session();
|
||||||
|
|
||||||
for (iterator i = m_peers.begin(); i != m_peers.end(); ++i)
|
for (iterator i = m_peers.begin(); i != m_peers.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->connection) continue;
|
if (i->connection) continue;
|
||||||
|
@ -533,6 +535,8 @@ namespace libtorrent
|
||||||
if (i->failcount >= max_failcount) continue;
|
if (i->failcount >= max_failcount) continue;
|
||||||
if (now - i->connected < seconds(i->failcount * min_reconnect_time))
|
if (now - i->connected < seconds(i->failcount * min_reconnect_time))
|
||||||
continue;
|
continue;
|
||||||
|
if (ses.m_port_filter.access(i->ip.port()) & port_filter::blocked)
|
||||||
|
continue;
|
||||||
|
|
||||||
assert(i->connected <= now);
|
assert(i->connected <= now);
|
||||||
|
|
||||||
|
@ -968,6 +972,19 @@ namespace libtorrent
|
||||||
if(remote.address() == address() || remote.port() == 0)
|
if(remote.address() == address() || remote.port() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
aux::session_impl& ses = m_torrent->session();
|
||||||
|
|
||||||
|
port_filter const& pf = ses.m_port_filter;
|
||||||
|
if (pf.access(remote.port()) & port_filter::blocked)
|
||||||
|
{
|
||||||
|
if (ses.m_alerts.should_post(alert::info))
|
||||||
|
{
|
||||||
|
ses.m_alerts.post_alert(peer_blocked_alert(remote.address()
|
||||||
|
, "outgoing port blocked, peer not added to peer list"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
iterator i;
|
iterator i;
|
||||||
|
@ -986,8 +1003,6 @@ namespace libtorrent
|
||||||
|
|
||||||
if (i == m_peers.end())
|
if (i == m_peers.end())
|
||||||
{
|
{
|
||||||
aux::session_impl& ses = m_torrent->session();
|
|
||||||
|
|
||||||
// if the IP is blocked, don't add it
|
// if the IP is blocked, don't add it
|
||||||
if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked)
|
if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked)
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,6 +143,11 @@ namespace libtorrent
|
||||||
m_impl->set_ip_filter(f);
|
m_impl->set_ip_filter(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session::set_port_filter(port_filter const& f)
|
||||||
|
{
|
||||||
|
m_impl->set_port_filter(f);
|
||||||
|
}
|
||||||
|
|
||||||
void session::set_peer_id(peer_id const& id)
|
void session::set_peer_id(peer_id const& id)
|
||||||
{
|
{
|
||||||
m_impl->set_peer_id(id);
|
m_impl->set_peer_id(id);
|
||||||
|
|
|
@ -582,6 +582,12 @@ namespace libtorrent { namespace detail
|
||||||
m_checker_impl.m_abort = true;
|
m_checker_impl.m_abort = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session_impl::set_port_filter(port_filter const& f)
|
||||||
|
{
|
||||||
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
m_port_filter = f;
|
||||||
|
}
|
||||||
|
|
||||||
void session_impl::set_ip_filter(ip_filter const& f)
|
void session_impl::set_ip_filter(ip_filter const& f)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
|
@ -171,6 +171,25 @@ int test_main()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port_filter pf;
|
||||||
|
|
||||||
|
// default contructed port filter should allow any port
|
||||||
|
TEST_CHECK(pf.access(0) == 0);
|
||||||
|
TEST_CHECK(pf.access(65535) == 0);
|
||||||
|
TEST_CHECK(pf.access(6881) == 0);
|
||||||
|
|
||||||
|
// block port 100 - 300
|
||||||
|
pf.add_rule(100, 300, port_filter::blocked);
|
||||||
|
|
||||||
|
TEST_CHECK(pf.access(0) == 0);
|
||||||
|
TEST_CHECK(pf.access(99) == 0);
|
||||||
|
TEST_CHECK(pf.access(100) == port_filter::blocked);
|
||||||
|
TEST_CHECK(pf.access(150) == port_filter::blocked);
|
||||||
|
TEST_CHECK(pf.access(300) == port_filter::blocked);
|
||||||
|
TEST_CHECK(pf.access(301) == 0);
|
||||||
|
TEST_CHECK(pf.access(6881) == 0);
|
||||||
|
TEST_CHECK(pf.access(65535) == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue