164 lines
5.3 KiB
Python
164 lines
5.3 KiB
Python
"""
|
|
security.py: defines security services (vpnclient, vpnserver, ipsec and
|
|
firewall)
|
|
"""
|
|
|
|
import logging
|
|
|
|
from core import constants
|
|
from core.nodes.base import CoreNode
|
|
from core.nodes.interface import CoreInterface
|
|
from core.services.coreservices import CoreService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class VPNClient(CoreService):
|
|
name: str = "VPNClient"
|
|
group: str = "Security"
|
|
configs: tuple[str, ...] = ("vpnclient.sh",)
|
|
startup: tuple[str, ...] = ("bash vpnclient.sh",)
|
|
shutdown: tuple[str, ...] = ("killall openvpn",)
|
|
validate: tuple[str, ...] = ("pidof openvpn",)
|
|
custom_needed: bool = True
|
|
|
|
@classmethod
|
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
|
"""
|
|
Return the client.conf and vpnclient.sh file contents to
|
|
"""
|
|
cfg = "#!/bin/sh\n"
|
|
cfg += "# custom VPN Client configuration for service (security.py)\n"
|
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNClient"
|
|
try:
|
|
with open(fname) as f:
|
|
cfg += f.read()
|
|
except OSError:
|
|
logger.exception(
|
|
"error opening VPN client configuration template (%s)", fname
|
|
)
|
|
return cfg
|
|
|
|
|
|
class VPNServer(CoreService):
|
|
name: str = "VPNServer"
|
|
group: str = "Security"
|
|
configs: tuple[str, ...] = ("vpnserver.sh",)
|
|
startup: tuple[str, ...] = ("bash vpnserver.sh",)
|
|
shutdown: tuple[str, ...] = ("killall openvpn",)
|
|
validate: tuple[str, ...] = ("pidof openvpn",)
|
|
custom_needed: bool = True
|
|
|
|
@classmethod
|
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
|
"""
|
|
Return the sample server.conf and vpnserver.sh file contents to
|
|
GUI for user customization.
|
|
"""
|
|
cfg = "#!/bin/sh\n"
|
|
cfg += "# custom VPN Server Configuration for service (security.py)\n"
|
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleVPNServer"
|
|
try:
|
|
with open(fname) as f:
|
|
cfg += f.read()
|
|
except OSError:
|
|
logger.exception(
|
|
"Error opening VPN server configuration template (%s)", fname
|
|
)
|
|
return cfg
|
|
|
|
|
|
class IPsec(CoreService):
|
|
name: str = "IPsec"
|
|
group: str = "Security"
|
|
configs: tuple[str, ...] = ("ipsec.sh",)
|
|
startup: tuple[str, ...] = ("bash ipsec.sh",)
|
|
shutdown: tuple[str, ...] = ("killall racoon",)
|
|
custom_needed: bool = True
|
|
|
|
@classmethod
|
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
|
"""
|
|
Return the ipsec.conf and racoon.conf file contents to
|
|
GUI for user customization.
|
|
"""
|
|
cfg = "#!/bin/sh\n"
|
|
cfg += "# set up static tunnel mode security assocation for service "
|
|
cfg += "(security.py)\n"
|
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleIPsec"
|
|
try:
|
|
with open(fname) as f:
|
|
cfg += f.read()
|
|
except OSError:
|
|
logger.exception("Error opening IPsec configuration template (%s)", fname)
|
|
return cfg
|
|
|
|
|
|
class Firewall(CoreService):
|
|
name: str = "Firewall"
|
|
group: str = "Security"
|
|
configs: tuple[str, ...] = ("firewall.sh",)
|
|
startup: tuple[str, ...] = ("bash firewall.sh",)
|
|
custom_needed: bool = True
|
|
|
|
@classmethod
|
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
|
"""
|
|
Return the firewall rule examples to GUI for user customization.
|
|
"""
|
|
cfg = "#!/bin/sh\n"
|
|
cfg += "# custom node firewall rules for service (security.py)\n"
|
|
fname = f"{constants.CORE_DATA_DIR}/examples/services/sampleFirewall"
|
|
try:
|
|
with open(fname) as f:
|
|
cfg += f.read()
|
|
except OSError:
|
|
logger.exception(
|
|
"Error opening Firewall configuration template (%s)", fname
|
|
)
|
|
return cfg
|
|
|
|
|
|
class Nat(CoreService):
|
|
"""
|
|
IPv4 source NAT service.
|
|
"""
|
|
|
|
name: str = "NAT"
|
|
group: str = "Security"
|
|
executables: tuple[str, ...] = ("iptables",)
|
|
configs: tuple[str, ...] = ("nat.sh",)
|
|
startup: tuple[str, ...] = ("bash nat.sh",)
|
|
custom_needed: bool = False
|
|
|
|
@classmethod
|
|
def generate_iface_nat_rule(cls, iface: CoreInterface, prefix: str = "") -> str:
|
|
"""
|
|
Generate a NAT line for one interface.
|
|
"""
|
|
cfg = prefix + "iptables -t nat -A POSTROUTING -o "
|
|
cfg += iface.name + " -j MASQUERADE\n"
|
|
cfg += prefix + "iptables -A FORWARD -i " + iface.name
|
|
cfg += " -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
|
cfg += prefix + "iptables -A FORWARD -i "
|
|
cfg += iface.name + " -j DROP\n"
|
|
return cfg
|
|
|
|
@classmethod
|
|
def generate_config(cls, node: CoreNode, filename: str) -> str:
|
|
"""
|
|
NAT out the first interface
|
|
"""
|
|
cfg = "#!/bin/sh\n"
|
|
cfg += "# generated by security.py\n"
|
|
cfg += "# NAT out the first interface by default\n"
|
|
have_nat = False
|
|
for iface in node.get_ifaces(control=False):
|
|
if have_nat:
|
|
cfg += cls.generate_iface_nat_rule(iface, prefix="#")
|
|
else:
|
|
have_nat = True
|
|
cfg += "# NAT out the " + iface.name + " interface\n"
|
|
cfg += cls.generate_iface_nat_rule(iface)
|
|
cfg += "\n"
|
|
return cfg
|