Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d1bafd9e7f
@ -31,6 +31,7 @@ rec {
|
|||||||
inherit pkgs modules baseModules;
|
inherit pkgs modules baseModules;
|
||||||
modulesPath = ../modules;
|
modulesPath = ../modules;
|
||||||
pkgs_i686 = import <nixpkgs> { system = "i686-linux"; };
|
pkgs_i686 = import <nixpkgs> { system = "i686-linux"; };
|
||||||
|
utils = {}; # forward compatibility
|
||||||
};
|
};
|
||||||
|
|
||||||
# Import Nixpkgs, allowing the NixOS option nixpkgs.config to
|
# Import Nixpkgs, allowing the NixOS option nixpkgs.config to
|
||||||
|
@ -18,13 +18,6 @@ let
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
localhostWithDomain = optionalString (cfg.domain != "")
|
|
||||||
"localhost.${cfg.domain}";
|
|
||||||
|
|
||||||
hostnameWithDomain = optionalString
|
|
||||||
(cfg.domain != "" && cfg.hostName != "")
|
|
||||||
"${cfg.hostName}.${cfg.domain}";
|
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -49,9 +42,8 @@ in
|
|||||||
{ # /etc/hosts: Hostname-to-IP mappings.
|
{ # /etc/hosts: Hostname-to-IP mappings.
|
||||||
source = pkgs.writeText "hosts"
|
source = pkgs.writeText "hosts"
|
||||||
''
|
''
|
||||||
${optionalString (cfg.hostName != "")
|
127.0.0.1 localhost
|
||||||
"127.0.0.1 ${hostnameWithDomain} ${cfg.hostName}"}
|
::1 localhost
|
||||||
127.0.0.1 localhost ${localhostWithDomain}
|
|
||||||
${cfg.extraHosts}
|
${cfg.extraHosts}
|
||||||
'';
|
'';
|
||||||
target = "hosts";
|
target = "hosts";
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
# NSS configuration files with mDNS enabled (requires running Avahi daemon).
|
|
||||||
|
|
||||||
passwd: ldap files
|
|
||||||
group: ldap files
|
|
||||||
shadow: ldap files
|
|
||||||
|
|
||||||
hosts: files mdns_minimal [NOTFOUND=return] dns mdns
|
|
||||||
networks: files dns
|
|
||||||
|
|
||||||
services: files
|
|
||||||
protocols: files
|
|
@ -1,10 +0,0 @@
|
|||||||
passwd: files ldap
|
|
||||||
group: files ldap
|
|
||||||
shadow: files ldap
|
|
||||||
|
|
||||||
hosts: files dns
|
|
||||||
networks: files dns
|
|
||||||
ethers: files
|
|
||||||
|
|
||||||
services: files
|
|
||||||
protocols: files
|
|
@ -1,13 +1,15 @@
|
|||||||
# Configuration for the Name Service Switch (/etc/nsswitch.conf).
|
# Configuration for the Name Service Switch (/etc/nsswitch.conf).
|
||||||
|
|
||||||
{config, pkgs, ...}:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
# NSS modules. Hacky!
|
# NSS modules. Hacky!
|
||||||
system.nssModules = pkgs.lib.mkOption {
|
system.nssModules = mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
default = [];
|
default = [];
|
||||||
description = "
|
description = "
|
||||||
@ -15,48 +17,49 @@ let
|
|||||||
several DNS resolution methods to be specified via
|
several DNS resolution methods to be specified via
|
||||||
<filename>/etc/nsswitch.conf</filename>.
|
<filename>/etc/nsswitch.conf</filename>.
|
||||||
";
|
";
|
||||||
merge = pkgs.lib.mergeListOption;
|
merge = mergeListOption;
|
||||||
apply = list:
|
apply = list:
|
||||||
let
|
let
|
||||||
list2 =
|
list2 =
|
||||||
list
|
list
|
||||||
# !!! this should be in the LDAP module
|
# !!! this should be in the LDAP module
|
||||||
++ pkgs.lib.optional config.users.ldap.enable pkgs.nss_ldap;
|
++ optional config.users.ldap.enable pkgs.nss_ldap;
|
||||||
in {
|
in {
|
||||||
list = list2;
|
list = list2;
|
||||||
path = pkgs.lib.makeLibraryPath list2;
|
path = makeLibraryPath list2;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inherit (config.services.avahi) nssmdns;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
require = [options];
|
require = [ options ];
|
||||||
|
|
||||||
environment.etc =
|
environment.etc =
|
||||||
[ # Name Service Switch configuration file. Required by the C library.
|
[ # Name Service Switch configuration file. Required by the C library.
|
||||||
# !!! Factor out the mdns stuff. The avahi module should define
|
# !!! Factor out the mdns stuff. The avahi module should define
|
||||||
# an option used by this module.
|
# an option used by this module.
|
||||||
{ source =
|
{ source = pkgs.writeText "nsswitch.conf"
|
||||||
if config.services.avahi.nssmdns
|
''
|
||||||
then ./nsswitch-mdns.conf
|
passwd: files ldap
|
||||||
else ./nsswitch.conf;
|
group: files ldap
|
||||||
|
shadow: files ldap
|
||||||
|
hosts: files ${optionalString nssmdns "mdns_minimal [NOTFOUND=return]"} dns ${optionalString nssmdns "mdns"} myhostname
|
||||||
|
networks: files dns
|
||||||
|
ethers: files
|
||||||
|
services: files
|
||||||
|
protocols: files
|
||||||
|
'';
|
||||||
target = "nsswitch.conf";
|
target = "nsswitch.conf";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.shellInit =
|
# Use nss-myhostname to ensure that our hostname always resolves to
|
||||||
if config.system.nssModules.path != "" then
|
# a valid IP address. It returns all locally configured IP
|
||||||
''
|
# addresses, or ::1 and 127.0.0.2 as fallbacks.
|
||||||
LD_LIBRARY_PATH=${config.system.nssModules.path}:$LD_LIBRARY_PATH
|
system.nssModules = [ pkgs.nss_myhostname ];
|
||||||
''
|
|
||||||
else "";
|
|
||||||
|
|
||||||
# NSS modules need to be in `systemPath' so that (i) the builder
|
|
||||||
# chroot gets to seem them, and (ii) applications can benefit from
|
|
||||||
# changes in the list of NSS modules at run-time, without requiring
|
|
||||||
# a reboot.
|
|
||||||
environment.systemPackages = [config.system.nssModules.list];
|
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
./services/networking/gnunet.nix
|
./services/networking/gnunet.nix
|
||||||
./services/networking/gogoclient.nix
|
./services/networking/gogoclient.nix
|
||||||
./services/networking/gvpe.nix
|
./services/networking/gvpe.nix
|
||||||
|
./services/networking/hostapd.nix
|
||||||
./services/networking/ifplugd.nix
|
./services/networking/ifplugd.nix
|
||||||
./services/networking/ircd-hybrid/default.nix
|
./services/networking/ircd-hybrid/default.nix
|
||||||
./services/networking/nat.nix
|
./services/networking/nat.nix
|
||||||
|
@ -7,6 +7,25 @@ with pkgs.lib;
|
|||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
|
initBashCompletion = optionalString config.environment.enableBashCompletion ''
|
||||||
|
# Check whether we're running a version of Bash that has support for
|
||||||
|
# programmable completion. If we do, enable all modules installed in
|
||||||
|
# the system (and user profile).
|
||||||
|
if shopt -q progcomp &>/dev/null; then
|
||||||
|
. "${pkgs.bashCompletion}/etc/profile.d/bash_completion.sh"
|
||||||
|
nullglobStatus=$(shopt -p nullglob)
|
||||||
|
shopt -s nullglob
|
||||||
|
for p in $NIX_PROFILES; do
|
||||||
|
for m in "$p/etc/bash_completion.d/"*; do
|
||||||
|
. $m
|
||||||
|
done
|
||||||
|
done
|
||||||
|
eval "$nullglobStatus"
|
||||||
|
unset nullglobStatus p m
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
environment.shellInit = mkOption {
|
environment.shellInit = mkOption {
|
||||||
@ -18,6 +37,12 @@ let
|
|||||||
type = with pkgs.lib.types; string;
|
type = with pkgs.lib.types; string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.enableBashCompletion = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = "Enable bash-completion for all interactive shells.";
|
||||||
|
type = with pkgs.lib.types; bool;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
@ -38,7 +63,10 @@ in
|
|||||||
{ # /etc/bashrc: executed every time a bash starts. Sources
|
{ # /etc/bashrc: executed every time a bash starts. Sources
|
||||||
# /etc/profile to ensure that the system environment is
|
# /etc/profile to ensure that the system environment is
|
||||||
# configured properly.
|
# configured properly.
|
||||||
source = ./bashrc.sh;
|
source = pkgs.substituteAll {
|
||||||
|
src = ./bashrc.sh;
|
||||||
|
inherit initBashCompletion;
|
||||||
|
};
|
||||||
target = "bashrc";
|
target = "bashrc";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,4 +87,5 @@ in
|
|||||||
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
|
mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
environment.pathsToLink = optional config.environment.enableBashCompletion "/etc/bash_completion.d";
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,7 @@ if test "$TERM" = "xterm"; then
|
|||||||
PS1="\[\033]2;\h:\u:\w\007\]$PS1"
|
PS1="\[\033]2;\h:\u:\w\007\]$PS1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check whether we're running a version of Bash that has support for
|
@initBashCompletion@
|
||||||
# programmable completion. If we do, and if the current user has
|
|
||||||
# installed the package 'bash-completion' in her $HOME/.nix-profile,
|
|
||||||
# then completion is enabled automatically.
|
|
||||||
if [ -f "$HOME/.nix-profile/etc/profile.d/bash_completion.sh" ]; then
|
|
||||||
if shopt -q progcomp &>/dev/null; then
|
|
||||||
. "$HOME/.nix-profile/etc/profile.d/bash_completion.sh"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Some aliases.
|
# Some aliases.
|
||||||
alias ls="ls --color=tty"
|
alias ls="ls --color=tty"
|
||||||
|
@ -5,16 +5,13 @@ with pkgs.lib;
|
|||||||
let
|
let
|
||||||
cfg = config.services.logcheck;
|
cfg = config.services.logcheck;
|
||||||
|
|
||||||
rulesDir = pkgs.runCommand "logcheck-rules-dir"
|
defaultRules = pkgs.runCommand "logcheck-default-rules" {} ''
|
||||||
{} (
|
cp -prd ${pkgs.logcheck}/etc/logcheck $out
|
||||||
''
|
chmod u+w $out
|
||||||
mkdir $out
|
rm $out/logcheck.*
|
||||||
cp -prd ${pkgs.logcheck}/etc/logcheck/* $out/
|
'';
|
||||||
rm $out/logcheck.*
|
|
||||||
chmod u+w $out/*
|
rulesDir = pkgs.symlinkJoin "logcheck-rules-dir" ([ defaultRules ] ++ cfg.extraRulesDirs);
|
||||||
'' + optionalString (! builtins.isNull cfg.extraRulesDir) ''
|
|
||||||
cp -prd ${cfg.extraRulesDir}/* $out/
|
|
||||||
'' );
|
|
||||||
|
|
||||||
configFile = pkgs.writeText "logcheck.conf" cfg.config;
|
configFile = pkgs.writeText "logcheck.conf" cfg.config;
|
||||||
|
|
||||||
@ -33,6 +30,74 @@ let
|
|||||||
2 ${cfg.timeOfDay} * * * logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
|
2 ${cfg.timeOfDay} * * * logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
writeIgnoreRule = name: {level, regex, ...}:
|
||||||
|
pkgs.writeTextFile
|
||||||
|
{ inherit name;
|
||||||
|
destination = "/ignore.d.${level}/${name}";
|
||||||
|
text = ''
|
||||||
|
^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}:
|
||||||
|
let escapeRegex = escape (stringToCharacters "\\[]{}()^$?*+|.");
|
||||||
|
cmdline_ = builtins.unsafeDiscardStringContext cmdline;
|
||||||
|
re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_;
|
||||||
|
in writeIgnoreRule "cron-${name}" {
|
||||||
|
inherit level;
|
||||||
|
regex = ''
|
||||||
|
(/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
levelOption = mkOption {
|
||||||
|
default = "server";
|
||||||
|
type = types.uniq types.string;
|
||||||
|
description = ''
|
||||||
|
Set the logcheck level. Either "workstation", "server", or "paranoid".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
ignoreOptions = {
|
||||||
|
level = levelOption;
|
||||||
|
|
||||||
|
regex = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.uniq types.string;
|
||||||
|
description = ''
|
||||||
|
Regex specifying which log lines to ignore.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ignoreCronOptions = {
|
||||||
|
user = mkOption {
|
||||||
|
default = "root";
|
||||||
|
type = types.uniq types.string;
|
||||||
|
description = ''
|
||||||
|
User that runs the cronjob.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
cmdline = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.uniq types.string;
|
||||||
|
description = ''
|
||||||
|
Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
timeArgs = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr (types.uniq types.string);
|
||||||
|
example = "02 06 * * *";
|
||||||
|
description = ''
|
||||||
|
"min hr dom mon dow" crontab time args, to auto-create a cronjob too.
|
||||||
|
Leave at null to not do this and just add a logcheck ignore rule.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
@ -98,16 +163,33 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
extraRulesDir = mkOption {
|
extraRulesDirs = mkOption {
|
||||||
default = null;
|
default = [];
|
||||||
example = "/etc/logcheck";
|
example = "/etc/logcheck";
|
||||||
type = types.nullOr types.path;
|
type = types.listOf types.path;
|
||||||
description = ''
|
description = ''
|
||||||
Directory with extra rules.
|
Directories with extra rules.
|
||||||
Will be merged with bundled rules, so it's possible to override certain behaviour.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ignore = mkOption {
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
This option defines extra ignore rules.
|
||||||
|
'';
|
||||||
|
type = types.loaOf types.optionSet;
|
||||||
|
options = [ ignoreOptions ];
|
||||||
|
};
|
||||||
|
|
||||||
|
ignoreCron = mkOption {
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
This option defines extra ignore rules for cronjobs.
|
||||||
|
'';
|
||||||
|
type = types.loaOf types.optionSet;
|
||||||
|
options = [ ignoreOptions ignoreCronOptions ];
|
||||||
|
};
|
||||||
|
|
||||||
extraGroups = mkOption {
|
extraGroups = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
type = types.listOf types.string;
|
type = types.listOf types.string;
|
||||||
@ -122,6 +204,10 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
services.logcheck.extraRulesDirs =
|
||||||
|
mapAttrsToList writeIgnoreRule cfg.ignore
|
||||||
|
++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
|
||||||
|
|
||||||
users.extraUsers = singleton
|
users.extraUsers = singleton
|
||||||
{ name = cfg.user;
|
{ name = cfg.user;
|
||||||
shell = "/bin/sh";
|
shell = "/bin/sh";
|
||||||
@ -134,6 +220,12 @@ in
|
|||||||
chown ${cfg.user} /var/{lib,lock}/logcheck
|
chown ${cfg.user} /var/{lib,lock}/logcheck
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services.cron.systemCronJobs = [ cronJob ];
|
services.cron.systemCronJobs =
|
||||||
|
let withTime = name: {timeArgs, ...}: ! (builtins.isNull timeArgs);
|
||||||
|
mkCron = name: {user, cmdline, timeArgs, ...}: ''
|
||||||
|
${timeArgs} ${user} ${cmdline}
|
||||||
|
'';
|
||||||
|
in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron)
|
||||||
|
++ [ cronJob ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ let
|
|||||||
|
|
||||||
smartdConf = pkgs.writeText "smartd.conf" (concatMapStrings (device:
|
smartdConf = pkgs.writeText "smartd.conf" (concatMapStrings (device:
|
||||||
''
|
''
|
||||||
${device} -a -m root -M exec ${smartdMail}
|
${device} -a -m root -M exec ${smartdMail} ${cfg.deviceOpts}
|
||||||
''
|
''
|
||||||
) cfg.devices);
|
) cfg.devices);
|
||||||
|
|
||||||
@ -50,6 +50,17 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deviceOpts = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.string;
|
||||||
|
example = "-o on -s (S/../.././02|L/../../7/04)";
|
||||||
|
description = ''
|
||||||
|
Additional options for each device that is monitored. The example
|
||||||
|
turns on SMART Automatic Offline Testing on startup, and schedules short
|
||||||
|
self-tests daily, and long self-tests weekly.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
devices = mkOption {
|
devices = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
example = ["/dev/sda" "/dev/sdb"];
|
example = ["/dev/sda" "/dev/sdb"];
|
||||||
|
@ -39,6 +39,15 @@ let
|
|||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
kernelPackages = config.boot.kernelPackages;
|
||||||
|
kernelHasRPFilter = kernelPackages.kernel ? features
|
||||||
|
&& kernelPackages.kernel.features ? netfilterRPFilter
|
||||||
|
&& kernelPackages.kernel.features.netfilterRPFilter;
|
||||||
|
|
||||||
|
kernelCanDisableHelpers = kernelPackages.kernel ? features
|
||||||
|
&& kernelPackages.kernel.features ? canDisableNetfilterConntrackHelpers
|
||||||
|
&& kernelPackages.kernel.features.canDisableNetfilterConntrackHelpers;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -140,6 +149,53 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.firewall.checkReversePath = mkOption {
|
||||||
|
default = kernelHasRPFilter;
|
||||||
|
type = types.bool;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
Performs a reverse path filter test on a packet.
|
||||||
|
If a reply to the packet would not be sent via the same interface
|
||||||
|
that the packet arrived on, it is refused.
|
||||||
|
|
||||||
|
If using asymmetric routing or other complicated routing,
|
||||||
|
disable this setting and setup your own counter-measures.
|
||||||
|
|
||||||
|
(needs kernel 3.3+)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.connectionTrackingModules = mkOption {
|
||||||
|
default = [ "ftp" ];
|
||||||
|
example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
|
||||||
|
type = types.list types.string;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
List of connection-tracking helpers that are auto-loaded.
|
||||||
|
The complete list of possible values is given in the example.
|
||||||
|
|
||||||
|
As helpers can pose as a security risk, it is adviced to
|
||||||
|
set this to an empty list and disable the setting
|
||||||
|
networking.firewall.autoLoadConntrackHelpers
|
||||||
|
|
||||||
|
Loading of helpers is recommended to be done through the new
|
||||||
|
CT target. More info:
|
||||||
|
https://home.regit.org/netfilter-en/secure-use-of-helpers/
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.autoLoadConntrackHelpers = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
Whether to auto-load connection-tracking helpers.
|
||||||
|
See the description at networking.firewall.connectionTrackingModules
|
||||||
|
|
||||||
|
(needs kernel 3.5+)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
networking.firewall.extraCommands = mkOption {
|
networking.firewall.extraCommands = mkOption {
|
||||||
default = "";
|
default = "";
|
||||||
example = "iptables -A INPUT -p icmp -j ACCEPT";
|
example = "iptables -A INPUT -p icmp -j ACCEPT";
|
||||||
@ -168,7 +224,16 @@ in
|
|||||||
|
|
||||||
environment.systemPackages = [ pkgs.iptables ];
|
environment.systemPackages = [ pkgs.iptables ];
|
||||||
|
|
||||||
boot.kernelModules = [ "nf_conntrack_ftp" ];
|
boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
|
||||||
|
boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) ''
|
||||||
|
options nf_conntrack nf_conntrack_helper=0
|
||||||
|
'';
|
||||||
|
|
||||||
|
assertions = [ { assertion = ! cfg.checkReversePath || kernelHasRPFilter;
|
||||||
|
message = "This kernel does not support rpfilter"; }
|
||||||
|
{ assertion = cfg.autoLoadConntrackHelpers || kernelCanDisableHelpers;
|
||||||
|
message = "This kernel does not support disabling conntrack helpers"; }
|
||||||
|
];
|
||||||
|
|
||||||
jobs.firewall =
|
jobs.firewall =
|
||||||
{ startOn = "started network-interfaces";
|
{ startOn = "started network-interfaces";
|
||||||
@ -233,6 +298,12 @@ in
|
|||||||
# The "nixos-fw" chain does the actual work.
|
# The "nixos-fw" chain does the actual work.
|
||||||
ip46tables -N nixos-fw
|
ip46tables -N nixos-fw
|
||||||
|
|
||||||
|
# Perform a reverse-path test to refuse spoofers
|
||||||
|
# For now, we just drop, as the raw table doesn't have a log-refuse yet
|
||||||
|
${optionalString (kernelHasRPFilter && cfg.checkReversePath) ''
|
||||||
|
ip46tables -A PREROUTING -t raw -m rpfilter --invert -j DROP
|
||||||
|
''}
|
||||||
|
|
||||||
# Accept all traffic on the trusted interfaces.
|
# Accept all traffic on the trusted interfaces.
|
||||||
${flip concatMapStrings cfg.trustedInterfaces (iface: ''
|
${flip concatMapStrings cfg.trustedInterfaces (iface: ''
|
||||||
ip46tables -A nixos-fw -i ${iface} -j nixos-fw-accept
|
ip46tables -A nixos-fw -i ${iface} -j nixos-fw-accept
|
||||||
|
155
modules/services/networking/hostapd.nix
Normal file
155
modules/services/networking/hostapd.nix
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
#
|
||||||
|
# asserts
|
||||||
|
# ensure that the nl80211 module is loaded/compiled in the kernel
|
||||||
|
# hwMode must be a/b/g
|
||||||
|
# channel must be between 1 and 13 (maybe)
|
||||||
|
# wpa_supplicant and hostapd on the same wireless interface doesn't make any sense
|
||||||
|
# perhaps an assertion that there is a dhcp server and a dns server on the IP address serviced by the hostapd?
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.hostapd;
|
||||||
|
|
||||||
|
configFile = pkgs.writeText "hostapd.conf"
|
||||||
|
''
|
||||||
|
interface=${cfg.interface}
|
||||||
|
driver=${cfg.driver}
|
||||||
|
ssid=${cfg.ssid}
|
||||||
|
hw_mode=${cfg.hwMode}
|
||||||
|
channel=${toString cfg.channel}
|
||||||
|
|
||||||
|
# logging (debug level)
|
||||||
|
logger_syslog=-1
|
||||||
|
logger_syslog_level=2
|
||||||
|
logger_stdout=-1
|
||||||
|
logger_stdout_level=2
|
||||||
|
|
||||||
|
ctrl_interface=/var/run/hostapd
|
||||||
|
ctrl_interface_group=${cfg.group}
|
||||||
|
|
||||||
|
${if cfg.wpa then ''
|
||||||
|
wpa=1
|
||||||
|
wpa_passphrase=${cfg.wpaPassphrase}
|
||||||
|
'' else ""}
|
||||||
|
|
||||||
|
${cfg.extraCfg}
|
||||||
|
'' ;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.hostapd = {
|
||||||
|
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Enable putting a wireless interface into infrastructure mode,
|
||||||
|
allowing other wireless devices to associate with the wireless interface and do
|
||||||
|
wireless networking. A simple access point will enable hostapd.wpa, and
|
||||||
|
hostapd.wpa_passphrase, hostapd.ssid, dhcpd on the wireless interface to
|
||||||
|
provide IP addresses to the associated stations, and nat (from the wireless
|
||||||
|
interface to an upstream interface).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
interface = mkOption {
|
||||||
|
default = "";
|
||||||
|
example = "wlan0";
|
||||||
|
description = ''
|
||||||
|
The interfaces <command>hostapd</command> will use.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
driver = mkOption {
|
||||||
|
default = "nl80211";
|
||||||
|
example = "hostapd";
|
||||||
|
type = types.string;
|
||||||
|
description = "Which driver hostapd will use. Most things will probably use the default.";
|
||||||
|
};
|
||||||
|
|
||||||
|
ssid = mkOption {
|
||||||
|
default = "nixos";
|
||||||
|
example = "mySpecialSSID";
|
||||||
|
type = types.string;
|
||||||
|
description = "SSID to be used in IEEE 802.11 management frames.";
|
||||||
|
};
|
||||||
|
|
||||||
|
hwMode = mkOption {
|
||||||
|
default = "b";
|
||||||
|
example = "g";
|
||||||
|
type = types.string;
|
||||||
|
description = "Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g";
|
||||||
|
};
|
||||||
|
|
||||||
|
channel = mkOption {
|
||||||
|
default = 7;
|
||||||
|
example = 11;
|
||||||
|
type = types.int;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
Channel number (IEEE 802.11)
|
||||||
|
Please note that some drivers do not use this value from hostapd and the
|
||||||
|
channel will need to be configured separately with iwconfig.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
default = "wheel";
|
||||||
|
example = "network";
|
||||||
|
type = types.string;
|
||||||
|
description = "members of this group can control hostapd";
|
||||||
|
};
|
||||||
|
|
||||||
|
wpa = mkOption {
|
||||||
|
default = true;
|
||||||
|
description = "enable WPA (IEEE 802.11i/D3.0) to authenticate to the access point";
|
||||||
|
};
|
||||||
|
|
||||||
|
wpaPassphrase = mkOption {
|
||||||
|
default = "my_sekret";
|
||||||
|
example = "any_64_char_string";
|
||||||
|
type = types.string;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
WPA-PSK (pre-shared-key) passphrase. Clients will need this
|
||||||
|
passphrase to associate with this access point. Warning: This passphrase will
|
||||||
|
get put into a world-readable file in the nix store.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraCfg = mkOption {
|
||||||
|
default = "";
|
||||||
|
example = ''
|
||||||
|
auth_algo=0
|
||||||
|
ieee80211n=1
|
||||||
|
ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40]
|
||||||
|
'';
|
||||||
|
type = types.string;
|
||||||
|
description = "Extra configuration options to put in the hostapd.conf";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.hostapd ];
|
||||||
|
|
||||||
|
jobs.hostapd =
|
||||||
|
{ startOn = "started network-interfaces";
|
||||||
|
stopOn = "stopping network-interfaces";
|
||||||
|
exec = "${pkgs.hostapd}/bin/hostapd ${configFile}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
# This module enables Network Address Translation (NAT).
|
# This module enables Network Address Translation (NAT).
|
||||||
|
# XXX: todo: support multiple upstream links
|
||||||
|
# see http://yesican.chsoft.biz/lartc/MultihomedLinuxNetworking.html
|
||||||
|
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
@ -25,13 +27,16 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
networking.nat.internalIPs = mkOption {
|
networking.nat.internalIPs = mkOption {
|
||||||
example = "192.168.1.0/24";
|
example = [ "192.168.1.0/24" ] ;
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
The IP address range for which to perform NAT. Packets
|
The IP address ranges for which to perform NAT. Packets
|
||||||
coming from these addresses and destined for the external
|
coming from these networks and destined for the external
|
||||||
interface will be rewritten.
|
interface will be rewritten.
|
||||||
'';
|
'';
|
||||||
|
# Backward compatibility: this used to be a single range instead
|
||||||
|
# of a list.
|
||||||
|
apply = x: if isList x then x else [x];
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.nat.externalInterface = mkOption {
|
networking.nat.externalInterface = mkOption {
|
||||||
@ -76,13 +81,17 @@ in
|
|||||||
''
|
''
|
||||||
iptables -t nat -F POSTROUTING
|
iptables -t nat -F POSTROUTING
|
||||||
iptables -t nat -X
|
iptables -t nat -X
|
||||||
|
''
|
||||||
|
+ (concatMapStrings (network:
|
||||||
|
''
|
||||||
iptables -t nat -A POSTROUTING \
|
iptables -t nat -A POSTROUTING \
|
||||||
-s ${cfg.internalIPs} -o ${cfg.externalInterface} \
|
-s ${network} -o ${cfg.externalInterface} \
|
||||||
${if cfg.externalIP == ""
|
${if cfg.externalIP == ""
|
||||||
then "-j MASQUERADE"
|
then "-j MASQUERADE"
|
||||||
else "-j SNAT --to-source ${cfg.externalIP}"}
|
else "-j SNAT --to-source ${cfg.externalIP}"}
|
||||||
|
''
|
||||||
|
) cfg.internalIPs) +
|
||||||
|
''
|
||||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@ -91,7 +100,5 @@ in
|
|||||||
iptables -t nat -F POSTROUTING
|
iptables -t nat -F POSTROUTING
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ let
|
|||||||
|
|
||||||
httpd = mainCfg.package;
|
httpd = mainCfg.package;
|
||||||
|
|
||||||
|
version24 = !versionOlder httpd.version "2.4";
|
||||||
|
|
||||||
httpdConf = mainCfg.configFile;
|
httpdConf = mainCfg.configFile;
|
||||||
|
|
||||||
php = pkgs.php.override { apacheHttpd = httpd; };
|
php = pkgs.php.override { apacheHttpd = httpd; };
|
||||||
@ -101,7 +103,8 @@ let
|
|||||||
"auth_basic" "auth_digest"
|
"auth_basic" "auth_digest"
|
||||||
|
|
||||||
# Authentication: is the user who he claims to be?
|
# Authentication: is the user who he claims to be?
|
||||||
"authn_file" "authn_dbm" "authn_anon" "authn_alias"
|
"authn_file" "authn_dbm" "authn_anon"
|
||||||
|
(if version24 then "authn_core" else "authn_alias")
|
||||||
|
|
||||||
# Authorization: is the user allowed access?
|
# Authorization: is the user allowed access?
|
||||||
"authz_user" "authz_groupfile" "authz_host"
|
"authz_user" "authz_groupfile" "authz_host"
|
||||||
@ -113,11 +116,31 @@ let
|
|||||||
"vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling"
|
"vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling"
|
||||||
"userdir" "alias" "rewrite" "proxy" "proxy_http"
|
"userdir" "alias" "rewrite" "proxy" "proxy_http"
|
||||||
]
|
]
|
||||||
|
++ optionals version24 [
|
||||||
|
"mpm_${mainCfg.multiProcessingModule}"
|
||||||
|
"authz_core"
|
||||||
|
"unixd"
|
||||||
|
]
|
||||||
++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
|
++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
|
||||||
++ optional enableSSL "ssl"
|
++ optional enableSSL "ssl"
|
||||||
++ extraApacheModules;
|
++ extraApacheModules;
|
||||||
|
|
||||||
|
|
||||||
|
allDenied = if version24 then ''
|
||||||
|
Require all denied
|
||||||
|
'' else ''
|
||||||
|
Order deny,allow
|
||||||
|
Deny from all
|
||||||
|
'';
|
||||||
|
|
||||||
|
allGranted = if version24 then ''
|
||||||
|
Require all granted
|
||||||
|
'' else ''
|
||||||
|
Order allow,deny
|
||||||
|
Allow from all
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
loggingConf = ''
|
loggingConf = ''
|
||||||
ErrorLog ${mainCfg.logDir}/error_log
|
ErrorLog ${mainCfg.logDir}/error_log
|
||||||
|
|
||||||
@ -186,8 +209,7 @@ let
|
|||||||
<Directory "${documentRoot}">
|
<Directory "${documentRoot}">
|
||||||
Options Indexes FollowSymLinks
|
Options Indexes FollowSymLinks
|
||||||
AllowOverride None
|
AllowOverride None
|
||||||
Order allow,deny
|
${allGranted}
|
||||||
Allow from all
|
|
||||||
</Directory>
|
</Directory>
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@ -241,12 +263,10 @@ let
|
|||||||
AllowOverride FileInfo AuthConfig Limit Indexes
|
AllowOverride FileInfo AuthConfig Limit Indexes
|
||||||
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
|
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
|
||||||
<Limit GET POST OPTIONS>
|
<Limit GET POST OPTIONS>
|
||||||
Order allow,deny
|
${allGranted}
|
||||||
Allow from all
|
|
||||||
</Limit>
|
</Limit>
|
||||||
<LimitExcept GET POST OPTIONS>
|
<LimitExcept GET POST OPTIONS>
|
||||||
Order deny,allow
|
${allDenied}
|
||||||
Deny from all
|
|
||||||
</LimitExcept>
|
</LimitExcept>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
@ -268,8 +288,7 @@ let
|
|||||||
Alias ${elem.urlPath} ${elem.dir}/
|
Alias ${elem.urlPath} ${elem.dir}/
|
||||||
<Directory ${elem.dir}>
|
<Directory ${elem.dir}>
|
||||||
Options +Indexes
|
Options +Indexes
|
||||||
Order allow,deny
|
${allGranted}
|
||||||
Allow from all
|
|
||||||
AllowOverride All
|
AllowOverride All
|
||||||
</Directory>
|
</Directory>
|
||||||
'';
|
'';
|
||||||
@ -286,6 +305,10 @@ let
|
|||||||
|
|
||||||
ServerRoot ${httpd}
|
ServerRoot ${httpd}
|
||||||
|
|
||||||
|
${optionalString version24 ''
|
||||||
|
DefaultRuntimeDir ${mainCfg.stateDir}/runtime
|
||||||
|
''}
|
||||||
|
|
||||||
PidFile ${mainCfg.stateDir}/httpd.pid
|
PidFile ${mainCfg.stateDir}/httpd.pid
|
||||||
|
|
||||||
${optionalString (mainCfg.multiProcessingModule != "prefork") ''
|
${optionalString (mainCfg.multiProcessingModule != "prefork") ''
|
||||||
@ -321,8 +344,7 @@ let
|
|||||||
AddHandler type-map var
|
AddHandler type-map var
|
||||||
|
|
||||||
<Files ~ "^\.ht">
|
<Files ~ "^\.ht">
|
||||||
Order allow,deny
|
${allDenied}
|
||||||
Deny from all
|
|
||||||
</Files>
|
</Files>
|
||||||
|
|
||||||
${mimeConf}
|
${mimeConf}
|
||||||
@ -340,16 +362,14 @@ let
|
|||||||
<Directory />
|
<Directory />
|
||||||
Options FollowSymLinks
|
Options FollowSymLinks
|
||||||
AllowOverride None
|
AllowOverride None
|
||||||
Order deny,allow
|
${allDenied}
|
||||||
Deny from all
|
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
# But do allow access to files in the store so that we don't have
|
# But do allow access to files in the store so that we don't have
|
||||||
# to generate <Directory> clauses for every generated file that we
|
# to generate <Directory> clauses for every generated file that we
|
||||||
# want to serve.
|
# want to serve.
|
||||||
<Directory /nix/store>
|
<Directory /nix/store>
|
||||||
Order allow,deny
|
${allGranted}
|
||||||
Allow from all
|
|
||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
# Generate directives for the main server.
|
# Generate directives for the main server.
|
||||||
@ -359,7 +379,8 @@ let
|
|||||||
${let
|
${let
|
||||||
ports = map getPort allHosts;
|
ports = map getPort allHosts;
|
||||||
uniquePorts = uniqList {inputList = ports;};
|
uniquePorts = uniqList {inputList = ports;};
|
||||||
in concatMapStrings (port: "NameVirtualHost *:${toString port}\n") uniquePorts
|
directives = concatMapStrings (port: "NameVirtualHost *:${toString port}\n") uniquePorts;
|
||||||
|
in optionalString (!version24) directives
|
||||||
}
|
}
|
||||||
|
|
||||||
${let
|
${let
|
||||||
@ -620,6 +641,10 @@ in
|
|||||||
''
|
''
|
||||||
mkdir -m 0750 -p ${mainCfg.stateDir}
|
mkdir -m 0750 -p ${mainCfg.stateDir}
|
||||||
chown root.${mainCfg.group} ${mainCfg.stateDir}
|
chown root.${mainCfg.group} ${mainCfg.stateDir}
|
||||||
|
${optionalString version24 ''
|
||||||
|
mkdir -m 0750 -p "${mainCfg.stateDir}/runtime"
|
||||||
|
chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime"
|
||||||
|
''}
|
||||||
mkdir -m 0700 -p ${mainCfg.logDir}
|
mkdir -m 0700 -p ${mainCfg.logDir}
|
||||||
|
|
||||||
${optionalString (mainCfg.documentRoot != null)
|
${optionalString (mainCfg.documentRoot != null)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user