mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
nic_router: use increasing src port for new nat
The NAT feature of the NIC router used to prefer re-using source ports that have been freed recently. From an external server's perspective, if a client dies and restarts, chances are high that the new connect arrives with the same source-IP/source-port as the old connection. The server has to forcefully reset the connection. If that happens a lot, the server may even start to ignore further connections from this IP/port combination for a while as a mitigation. This patch adds a continuous counter feature that makes sure that every new port allocation will increment and result in a port that hasn't been used for a long time. The NAT feature of the nic_router is now more in line with RFC 6056 chapter 4. Ref #4086
This commit is contained in:
parent
ce75b25fd4
commit
4e822436fc
@ -313,7 +313,7 @@ void Domain::init(Domain_tree &domains)
|
||||
try {
|
||||
Nat_rule &rule = *new (_alloc)
|
||||
Nat_rule(domains, _tcp_port_alloc, _udp_port_alloc,
|
||||
_icmp_port_alloc, node);
|
||||
_icmp_port_alloc, node, _config.verbose());
|
||||
_nat_rules.insert(&rule);
|
||||
if (_config.verbose()) {
|
||||
log("[", *this, "] NAT rule: ", rule); }
|
||||
|
@ -47,12 +47,13 @@ Nat_rule::Nat_rule(Domain_tree &domains,
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Port_allocator &icmp_port_alloc,
|
||||
Xml_node const node)
|
||||
Xml_node const node,
|
||||
bool const verbose)
|
||||
:
|
||||
_domain(_find_domain(domains, node)),
|
||||
_tcp_port_alloc (tcp_port_alloc, node.attribute_value("tcp-ports", 0UL)),
|
||||
_udp_port_alloc (udp_port_alloc, node.attribute_value("udp-ports", 0UL)),
|
||||
_icmp_port_alloc(icmp_port_alloc, node.attribute_value("icmp-ids", 0UL))
|
||||
_tcp_port_alloc (tcp_port_alloc, node.attribute_value("tcp-ports", 0UL), verbose),
|
||||
_udp_port_alloc (udp_port_alloc, node.attribute_value("udp-ports", 0UL), verbose),
|
||||
_icmp_port_alloc(icmp_port_alloc, node.attribute_value("icmp-ids", 0UL), verbose)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -54,7 +54,8 @@ class Net::Nat_rule : public Genode::Avl_node<Nat_rule>
|
||||
Port_allocator &tcp_port_alloc,
|
||||
Port_allocator &udp_port_alloc,
|
||||
Port_allocator &icmp_port_alloc,
|
||||
Genode::Xml_node const node);
|
||||
Genode::Xml_node const node,
|
||||
bool const verbose);
|
||||
|
||||
Nat_rule &find_by_domain(Domain &domain);
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
|
||||
/* local includes */
|
||||
#include <port_allocator.h>
|
||||
|
||||
@ -26,6 +29,24 @@ bool Net::dynamic_port(Port const port) {
|
||||
** Port_allocator **
|
||||
********************/
|
||||
|
||||
Port Net::Port_allocator::alloc()
|
||||
{
|
||||
for (unsigned nr_of_trials { 0 };
|
||||
nr_of_trials < COUNT;
|
||||
nr_of_trials++) {
|
||||
|
||||
uint16_t const port_offset = _next_port_offset;
|
||||
_next_port_offset = (_next_port_offset + 1) % COUNT;
|
||||
try {
|
||||
_alloc.alloc_addr(port_offset);
|
||||
return Port { (uint16_t)(port_offset + FIRST) };
|
||||
}
|
||||
catch (Bit_allocator<COUNT>::Range_conflict) { }
|
||||
}
|
||||
throw Out_of_indices();
|
||||
}
|
||||
|
||||
|
||||
void Net::Port_allocator::alloc(Port const port)
|
||||
{
|
||||
try { _alloc.alloc_addr(port.value - FIRST); }
|
||||
@ -34,6 +55,12 @@ void Net::Port_allocator::alloc(Port const port)
|
||||
}
|
||||
|
||||
|
||||
void Port_allocator::free(Port const port)
|
||||
{
|
||||
_alloc.free(port.value - FIRST);
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
** Port_allocator_guard **
|
||||
**************************/
|
||||
@ -67,7 +94,15 @@ void Port_allocator_guard::free(Port const port)
|
||||
|
||||
|
||||
Port_allocator_guard::Port_allocator_guard(Port_allocator &port_alloc,
|
||||
unsigned const max)
|
||||
unsigned const max,
|
||||
bool const verbose)
|
||||
:
|
||||
_port_alloc(port_alloc), _max(max)
|
||||
{ }
|
||||
_port_alloc(port_alloc),
|
||||
_max(min(max, static_cast<uint16_t>(Port_allocator::COUNT)))
|
||||
{
|
||||
if (verbose && max > (Port_allocator::COUNT)) {
|
||||
|
||||
warning("number of ports was truncated to capacity of allocator");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,18 @@ class Net::Port_allocator
|
||||
private:
|
||||
|
||||
Genode::Bit_allocator<COUNT> _alloc { };
|
||||
Genode::uint16_t _next_port_offset { 0 };
|
||||
|
||||
public:
|
||||
|
||||
struct Allocation_conflict : Genode::Exception { };
|
||||
struct Out_of_indices : Genode::Exception { };
|
||||
|
||||
Port alloc() { return Port(_alloc.alloc() + FIRST); }
|
||||
Port alloc();
|
||||
|
||||
void alloc(Port const port);
|
||||
|
||||
void free(Port const port) { _alloc.free(port.value - FIRST); }
|
||||
void free(Port const port);
|
||||
};
|
||||
|
||||
|
||||
@ -70,7 +72,9 @@ class Net::Port_allocator_guard
|
||||
|
||||
void free(Port const port);
|
||||
|
||||
Port_allocator_guard(Port_allocator & port_alloc, unsigned const max);
|
||||
Port_allocator_guard(Port_allocator &port_alloc,
|
||||
unsigned const max,
|
||||
bool const verbose);
|
||||
|
||||
unsigned max() const { return _max; }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user