Currently the NixOS firewall will block all ports by default, except for port 22 if openssh is enabled. Why does this special behavior apply only to ssh? It would be very nice if we could create an option for the firewall that would allow services to automatically allow traffic to their specified ports.
This will smooth out a pretty big pain point, because while blocking all traffic by default is good security practice it can be really disorienting for users. NixOS declarative nature means we know which services are enabled and on which ports they should be listening. This means the firewall can automatically listen only on ports with configured services.
This would require all services that listen on ports to support this, but I think it would be a phenomenal idea that would make it way easier for people to get started with NixOS.
It's not a special behavior, it's up to the service to configure the firewall. The options already exists: adding the listen port to networking.firewall.allowed{UDP,TCP}Ports
will do. It just that not so many services are doing this.
Currently the NixOS firewall will block all ports by default,
That is the behaviour I expect.
except for port 22 if openssh is enabled.
I put port 22 explicitly into my firewall config. IMHO no service
should enable this itself so I don't really like this.
Why does this special behavior apply only to ssh? It would be very
nice if we could create an option for the firewall that would allow
services to automatically allow traffic to their specified ports.This will smooth out a pretty big pain point, because while blocking all traffic
by default is good security practice it can be really disorienting for users.
NixOS declarative nature means we know which services are enabled and on which
ports they should be listening. This means the firewall can automatically listen
only on ports with configured services.This would require all services that listen on ports to support this, but I think
it would be a phenomenal idea that would make it way easier for people to get
started with NixOS.
You could as well get the same effect by turning the firewall off.
While it is true that services can be configured to enable their ports, as @tohl mentions not all users want this.
Adding an option to the NixOS firewall that would say "Yes I want services to enable their ports" would allow services to conveniently enable their ports, while giving users the freedom to disable that option and manage all their ports manually.
Right now there are no options specifying whether services should be allowed to configure the firewall. This means that if they are doing it, like openssh, they aren't giving users the flexibility of choice. It also means that most services won't be written to enable their ports as the only way to do so is without the users explicit consent.
I believe adding an option to the firewall module that services could then respect would be an ideal solution as it would allow more flexibility then we currently have.
In https://github.com/NixOS/nixpkgs/pull/12957 it was discussed whether the firewall should be enabled by default or not. The PR proposed changing the default value, and some also discussed whether modules should be allowed to open ports or not. Because it isn't obvious from the generated configuration.nix
that the firewall is active it was discussed that at least the default value should be put in the generated configuration to that it is obvious.
How about we do the following:
/nixos-generate-config.pl
as proposed also in #12957. This will make it easier for users to find out why certain services are unreachable.This has been discussed in the past, but the consensus was that services shouldn't open ports in the firewall automatically because this should be an admin decision. For example, just because I have Apache httpd running, doesn't mean I want to open it to the outside world (I'm just running it for testing). Even (say) a DHCP server may not be outward facing - I could use it to provide DHCP to local containers. SSH was an exception for historical reasons (we didn't want to risk locking people out of their machines by blocking port 22), IIRC.
However, we could add some convenience options like services.httpd.openInFirewall
(_not_ a global option to open all enabled services in the firewall please...).
And most importantly, document the convention so it can be linked if such questions come up again.
And most importantly, document the convention so it can be linked if such questions come up again.
It is actually documented by now - nixpkgs-manual: 12.4. New modules:
- Ensure that the module respect other modules functionality.
- For example, enabling a module should not open firewall ports by default.
This has been discussed in the past, but the consensus was that services shouldn't open ports in the firewall automatically because this should be an admin decision.
+1
And I would also suggest removing that functionality from the openssh
module (for the next release). Especially since this can cause unexpected problems, e.g. by using the following option:
services.openssh.listenAddresses = [ {
addr = "192.168.1.1";
port = 123;
} ];
Now OpenSSH will be listening on port 123 but since services.openssh.ports
is still set to [ 22 ]
the firewall will be accepting new TCP connections to port 22 but not to port 123.
SSH was an exception for historical reasons (we didn't want to risk locking people out of their machines by blocking port 22), IIRC.
This is indeed a big problem (they should be able to fix this by booting to an older configuration via GRUB tho).
But we could probably find a way to create a smooth transition, e.g. by:
1) Including that in the release notes (+ email, website (download section), etc.)
2) Print a warning if OpenSSH is enabled (and the port isn't in allowedTCPPorts
)
Or we should at least add an option like openInFirewall
and probably change that default to false after printing a warning for a while (imho).
I would define services instead of plain ports:
A service specifies what ip:port combinations it uses and there is a way to allow a such services in the firewall. This way we no longer need to add an option to each service to open the firewall. And we can detect collisions between services. if multiple services for example try to bind 0.0.0.0:123 (ntp - https://github.com/NixOS/nixpkgs/pull/21160#issuecomment-270053234).
Example (naming/arguments could be improved, I just want to show who holds the information)
# ./nixos/modules/services/mail/postfix.nix
service.postfix.ports.smtp = mkPort {
port = 25;
protocol = "tcp";
};
service.postfix.ports.submission = mkPort {
port = 587;
protocol = "tcp";
};
# configuration.nix
# allow everything
networking.firewall.allowPorts = [ service.postfix.ports ];
# or just allow smtp
networking.firewall.allowPorts = [ service.postfix.ports.smtp ];
# ./nixos/modules/services/web-servers/caddy.nix
service.caddy.ports.http-alt = mkPort {
port = 8080;
address = "127.0.0.1";
protocol = "tcp";
};
# configuration.nix
# port forwarding (also useful for containers/other hosts)
networking.firewall.nat = [{
from = mkPort {
port = 80;
protocol = "tcp";
};
to = service.caddy.ports.http-alt;
}];
# ./nixos/modules/services/networking/bird.nix
# other protocols then tcp/udp - technically this is no longer a port. That's way I would suggest to use the term service instead of port.
service.postfix.ports.ospf = mkPort {
protocol = "ospf";
};
This approach also allows to open ports just for specific source/destination ips (Firewall zones) and the information can be also used for other firewall implementations (ufw, ferm, nftables).
What if enabling services, while not allowing their ports through the firewall raised an info/warning message during the nixos-rebuild. IMO this would make it lot more intuitive.
Hi,
Le 6 mai 2017 Γ 15:27, Roger Qiu notifications@github.com a Γ©crit :
What if enabling services, while not allowing their ports through the firewall raised an info/warning message during the nixos-rebuild. IMO this would make it lot more intuitive.
I disagree.
Opening service to the world (open firewall) should be (like current design) an active configuration from system admin.
Some services (example: web services) must be proxified to add a SSL/TLS layer.
With an auto-open rule, thoses services will be a threat.
I also have services allowed only through VPN. An auto-open port policy, would be harder to check than a default-closes policy.
example: a skipper to enable nix-serve-server only for VPN
file: nix-serve-server.nix:
included in /etc/nixos/configuration.nix
βββββββββ
{ config, lib, pkgs, ... }:
{
# Services
services.nix-serve = {
enable = true;
};
# Network
networking.firewall = {
allowedTCPPorts = [
#5000 # would open globally for everyone
];
allowedUDPPorts = [
];
extraCommands = ''
iptables -A INPUT -i tinc.tnet -p tcp --dport 5000 -j ACCEPT
ip6tables -A INPUT -i tinc.tnet -p tcp --dport 5000 -j ACCEPT
'';
};
}
βββββββββ
@jpierre03 Are you disagreeing with making nixos-rebuild notify the user that a service activated doesn't have any open ports (ultimately a ux feature)? Because it seems you're disagreeing with auto-opening ports (a security feature as well).
@CMCDragonkai Yes I disagree with auto-opening ports.
@Mic92 I have a working prototype of more or less what you described here: https://github.com/Infinisil/nixpkgs/blob/ports/nixos/modules/config/ports.nix
It allows setting
networking.tcpServicePorts = {
bar = [
{ addr = "192.168.1.1"; port = 80; }
];
foo = [
{ addr = "any"; port = 80; }
{ addr = "127.0.0.1"; port = 8080; }
];
}
Which would result in a warning
Port 80 problems:
has both bindings for any and addresses 192.168.1.1
I originally made this to prevent errors from services starting at the same port, but this could also be extended to support some nice firewall opening mechanism.
Taking out of 18.09, and I wonder if this ticket should be closed in favor of a ticket specific to the ideas presented later in the issue.
We don't want to automatically open the firewall (but might add convenience options where helpful), see around https://github.com/NixOS/nixpkgs/issues/19504#issuecomment-253458728.
W.r.t implementing other suggestions from here, please open separate issues :-)
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
https://discourse.nixos.org/t/overwrite-firewall-settings/9343/9
Most helpful comment
I would define services instead of plain ports:
A service specifies what ip:port combinations it uses and there is a way to allow a such services in the firewall. This way we no longer need to add an option to each service to open the firewall. And we can detect collisions between services. if multiple services for example try to bind 0.0.0.0:123 (ntp - https://github.com/NixOS/nixpkgs/pull/21160#issuecomment-270053234).
Example (naming/arguments could be improved, I just want to show who holds the information)
This approach also allows to open ports just for specific source/destination ips (Firewall zones) and the information can be also used for other firewall implementations (ufw, ferm, nftables).