Add support for zones in firewall service

This commit is contained in:
Sunil Mohan Adapa 2014-04-27 18:16:32 +05:30
parent 428d5e6aa3
commit 3ef1ed83ce
6 changed files with 114 additions and 70 deletions

View File

@ -22,8 +22,6 @@ Configuration helper for Plinth firewall inteface
"""
import argparse
import os
import re
import subprocess
@ -37,18 +35,31 @@ def parse_arguments():
help='Get whether firewalld is installed')
# Get status
subparsers.add_parser('get-status', help='Get whether firewalld is running')
subparsers.add_parser('get-status',
help='Get whether firewalld is running')
# Get service status
subparsers.add_parser('get-enabled-services', help='Get list of enabled services')
get_enabled_services = subparsers.add_parser(
'get-enabled-services', help='Get list of enabled services')
get_enabled_services.add_argument(
'--zone', help='Zone from which the list is to be retrieved',
required=True)
# Add a service
add_service = subparsers.add_parser('add-service', help='Add a service')
add_service.add_argument('service', help='Name of the service to add')
add_service.add_argument('--zone',
help='Zone to which service is to be added',
required=True)
# Remove a service status
remove_service = subparsers.add_parser('remove-service', help='Remove a service')
remove_service.add_argument('service', help='Name of the service to remove')
remove_service = subparsers.add_parser('remove-service',
help='Remove a service')
remove_service.add_argument('service',
help='Name of the service to remove')
remove_service.add_argument(
'--zone', help='Zone from which service is to be removed',
required=True)
return parser.parse_args()
@ -66,21 +77,26 @@ def subcommand_get_status(_):
subprocess.call(['firewall-cmd', '--state'])
def subcommand_get_enabled_services(_):
def subcommand_get_enabled_services(arguments):
"""Print the status of variours services"""
subprocess.call(['firewall-cmd', '--list-services'])
subprocess.call(['firewall-cmd', '--zone', arguments.zone,
'--list-services'])
def subcommand_add_service(arguments):
"""Permit a service in the firewall"""
subprocess.call(['firewall-cmd', '--add-service', arguments.service])
subprocess.call(['firewall-cmd', '--permanent', '--add-service', arguments.service])
subprocess.call(['firewall-cmd', '--zone', arguments.zone, '--add-service',
arguments.service])
subprocess.call(['firewall-cmd', '--zone', arguments.zone, '--permanent',
'--add-service', arguments.service])
def subcommand_remove_service(arguments):
"""Block a service in the firewall"""
subprocess.call(['firewall-cmd', '--remove-service', arguments.service])
subprocess.call(['firewall-cmd', '--permanent', '--remove-service', arguments.service])
subprocess.call(['firewall-cmd', '--zone', arguments.zone,
'--remove-service', arguments.service])
subprocess.call(['firewall-cmd', '--zone', arguments.zone, '--permanent',
'--remove-service', arguments.service])
def main():

View File

@ -1,48 +1,56 @@
#!/bin/sh
# Setup firewall rules for all the enabled services
# Ideally all non essential services are enabled from Plinth
# which automatically takes care of enabling appropirate firewall
# ports. This file is used then for essential services and services
# that are not yet configurable from Plinth.
# Setup firewall rules for all the services enabled by default.
# Ideally all non-essential services are enabled from Plinth which
# automatically takes care of enabling appropirate firewall ports. The
# following is then for essential services and services that are not
# yet configurable from Plinth.
# HTTP (JWChat, ownCloud)
firewall-cmd --permanent --add-service=http
firewall-cmd --zone=external --permanent --add-service=http
firewall-cmd --zone=internal --permanent --add-service=http
# HTTPS (Plinth, JWChat, ownCloud)
firewall-cmd --permanent --add-service=https
firewall-cmd --zone=external --permanent --add-service=https
firewall-cmd --zone=internal --permanent --add-service=https
# Tor
firewall-cmd --permanent --add-port=9050/tcp
firewall-cmd --zone=internal --permanent --add-service=tor-socks
# NTP
firewall-cmd --permanent --add-service=ntp
firewall-cmd --zone=internal --permanent --add-service=ntp
# DNS
firewall-cmd --permanent --add-service=dns
firewall-cmd --zone=internal --permanent --add-service=dns
# mDNS
firewall-cmd --permanent --add-service=mdns
firewall-cmd --zone=internal --permanent --add-service=mdns
# DHCP
firewall-cmd --permanent --add-service=dhcp
firewall-cmd --zone=internal --permanent --add-service=dhcp
# Bootp Server and Client (not enabled)
#firewall-cmd --permanent --add-port=67/tcp
#firewall-cmd --permanent --add-port=67/udp
#firewall-cmd --permanent --add-port=68/tcp
#firewall-cmd --permanent --add-port=68/udp
#firewall-cmd --zone=internal --permanent --add-port=67/tcp
#firewall-cmd --zone=internal --permanent --add-port=67/udp
#firewall-cmd --zone=internal --permanent --add-port=68/tcp
#firewall-cmd --zone=internal --permanent --add-port=68/udp
# LDAP (not enabled)
#firewall-cmd --permanent --add-service=ldap
#firewall-cmd --permanent --add-service=ldaps
#firewall-cmd --zone=internal --permanent --add-service=ldap
#firewall-cmd --zone=internal --permanent --add-service=ldaps
# OpenVPN (not enabled)
#firewall-cmd --permanent --add-service=openvpn
#firewall-cmd --zone=external --permanent --add-service=openvpn
#firewall-cmd --zone=internal --permanent --add-service=openvpn
# Privoxy
firewall-cmd --permanent --add-port=8118/tcp
firewall-cmd --zone=internal --permanent --add-service=privoxy
# Obfsproxy
firewall-cmd --permanent --add-port=40202/tcp
# XMPP
firewall-cmd --zone=external --permanent --add-service=xmpp-server
firewall-cmd --zone=internal --permanent --add-service=xmpp-server
firewall-cmd --zone=external --permanent --add-service=xmpp-client
firewall-cmd --zone=internal --permanent --add-service=xmpp-client
firewall-cmd --zone=external --permanent --add-service=xmpp-bosh
firewall-cmd --zone=internal --permanent --add-service=xmpp-bosh

View File

@ -17,7 +17,7 @@ class Owncloud(PagePlugin, FormPlugin):
cfg.html_root.apps.menu.add_item("Owncloud", "icon-picture", "/apps/owncloud", 35)
self.service = service.Service('owncloud', _('ownCloud'),
['http', 'https'],
['http', 'https'], is_external=True,
enabled=self.is_enabled)
def is_enabled(self):

View File

@ -17,22 +17,14 @@ class xmpp(PagePlugin):
cfg.html_root.services.menu.add_item("XMPP", "icon-comment", "/services/xmpp", 40)
self.client_service = service.Service(
'xmpp-client', _('Chat Server - client connections'), enabled=True)
'xmpp-client', _('Chat Server - client connections'),
is_external=True, enabled=True)
self.server_service = service.Service(
'xmpp-server', _('Chat Server - server connections'), enabled=True)
'xmpp-server', _('Chat Server - server connections'),
is_external=True, enabled=True)
self.bosh_service = service.Service(
'xmpp-bosh', _('Chat Server - web interface'), enabled=True)
# XXX: This is not correct. This essentially triggers firewall
# to enable XMPP ports. This happen on every start of
# Plinth. XMPP should be an option to be enabled on Plinth. If
# and when the user enables the following notifications must
# sent. If XMPP has be on by default in FreedomBox, then
# initial setup process that sets up XMPP also must open the
# firewall ports by default.
self.client_service.notify_enabled(self, enabled=True)
self.server_service.notify_enabled(self, enabled=True)
self.bosh_service.notify_enabled(self, enabled=True)
'xmpp-bosh', _('Chat Server - web interface'), is_external=True,
enabled=True)
@cherrypy.expose
@require()

View File

@ -77,7 +77,9 @@ or in case of system with systemd 'systemctl start firewalld'</p>
return self.fill_template(title=_("Firewall"), main=main + status)
enabled_services = self.get_enabled_services()
internal_enabled_sevices = self.get_enabled_services(zone='internal')
external_enabled_sevices = self.get_enabled_services(zone='external')
services_info = '<ul>'
for service in service_module.SERVICES.values():
if service.is_enabled():
@ -89,9 +91,16 @@ or in case of system with systemd 'systemctl start firewalld'</p>
port_info = []
for port in service.ports:
if port in enabled_services:
if port in internal_enabled_sevices and \
port in external_enabled_sevices:
text = _('Permitted')
css_class = 'firewall-permitted'
elif port in internal_enabled_sevices:
text = _('Permitted (internal only)')
css_class = 'firewall-permitted'
elif port in external_enabled_sevices:
text = _('Permitted (external only)')
css_class = 'firewall-permitted'
else:
text = _('Blocked')
css_class = 'firewall-blocked'
@ -133,18 +142,18 @@ a service is automatically disabled in the firewall.</em></p>'''
output = self._run(['get-status'])
return output.split()[0] == 'running'
def get_enabled_services(self):
def get_enabled_services(self, zone):
"""Return the status of various services currently enabled"""
output = self._run(['get-enabled-services'])
output = self._run(['get-enabled-services', '--zone', zone])
return output.split()
def add_service(self, port):
def add_service(self, port, zone):
"""Enable a service in firewall"""
self._run(['add-service', port])
self._run(['add-service', port, '--zone', zone])
def remove_service(self, port):
def remove_service(self, port, zone):
"""Remove a service in firewall"""
self._run(['remove-service', port])
self._run(['remove-service', port, '--zone', zone])
def on_service_enabled(self, sender, service_id, enabled, **kwargs):
"""
@ -154,22 +163,38 @@ a service is automatically disabled in the firewall.</em></p>'''
del sender # Unused
del kwargs # Unused
enabled_services = self.get_enabled_services()
internal_enabled_services = self.get_enabled_services(zone='internal')
external_enabled_services = self.get_enabled_services(zone='external')
cfg.log.info('Service enabled - %s, %s' % (service_id, enabled))
for port in service_module.SERVICES[service_id].ports:
service = service_module.SERVICES[service_id]
for port in service.ports:
if enabled:
if port not in enabled_services:
self.add_service(port)
if port not in internal_enabled_services:
self.add_service(port, zone='internal')
if service.is_external and \
port not in external_enabled_services:
self.add_service(port, zone='external')
else:
if port in enabled_services:
if port in internal_enabled_services:
enabled_services_on_port = [
service_.is_enabled()
for service_ in service_module.SERVICES.values()
if port in service_.ports and
service_id != service_.service_id]
if not any(enabled_services_on_port):
self.remove_service(port)
self.remove_service(port, zone='internal')
if port in external_enabled_services:
enabled_services_on_port = [
service_.is_enabled()
for service_ in service_module.SERVICES.values()
if port in service_.ports and
service_id != service_.service_id and
service_.is_external]
if not any(enabled_services_on_port):
self.remove_service(port, zone='external')
@staticmethod
def _run(arguments, superuser=True):

View File

@ -35,13 +35,15 @@ class Service(object):
for operation.
"""
def __init__(self, service_id, name, ports=None, enabled=True):
def __init__(self, service_id, name, ports=None, is_external=False,
enabled=True):
if not ports:
ports = [service_id]
self.service_id = service_id
self.name = name
self.ports = ports
self.is_external = is_external
self._enabled = enabled
# Maintain a complete list of services
@ -65,9 +67,10 @@ class Service(object):
def init():
"""Register some misc. services that don't fit elsewhere"""
Service('http', _('Web Server'), ['http'], True)
Service('https', _('Web Server over Secure Socket Layer'),
['https'], True)
Service('ssh', _('Secure Shell (SSH) Server'), ['ssh'], True)
Service('plinth', _('FreedomBox Web Interface (Plinth)'),
['https'], True)
Service('http', _('Web Server'), ['http'], is_external=True, enabled=True)
Service('https', _('Web Server over Secure Socket Layer'), ['https'],
is_external=True, enabled=True)
Service('ssh', _('Secure Shell (SSH) Server'), ['ssh'], is_external=True,
enabled=True)
Service('plinth', _('FreedomBox Web Interface (Plinth)'), ['https'],
is_external=True, enabled=True)