privoxy: Restrict to private IPs, prevent access over the internet

- Make sure a user might not run Privoxy as an open proxy, potentially giving
unwanted access to local resources. Only private IP classes are allowed to
connect.

Tests:

- Freshly install privoxy app. permit-access directives are set in the
configuration. Proxy works when tested with a private IP address with Firefox.

- Install privoxy app without the changes. Apply the changes, privoxy setup
should run. permit-access directives are set in the configuration. Proxy works
when tested with a private IP address with Firefox.

- Privoxy works when accessed with IPv4 address (such as 10.42.0.x) and IPv6
address (such as fe80:y:z%ve-fbx-testing).

[sunil: Use Spacevars augeus lens to edit the configuration file]
[sunil: Update IP ranges with auto-configuration, IPv6 addresses, etc.]
[sunil: Update description to mention that only local IPs are allowed]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
nbenedek 2022-06-27 17:49:24 +02:00 committed by Sunil Mohan Adapa
parent 864c269f3d
commit de2c246dbd
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
2 changed files with 53 additions and 2 deletions

View File

@ -5,9 +5,14 @@ Configuration helper for Privoxy server.
"""
import argparse
import pathlib
import augeas
from plinth import action_utils
PRIVOXY_CONF_PATH = pathlib.Path('/etc/privoxy/config')
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
@ -17,6 +22,7 @@ def parse_arguments():
subparsers.add_parser(
'pre-install',
help='Preseed debconf values before packages are installed')
subparsers.add_parser('setup', help='Perform post install steps')
subparsers.required = True
return parser.parse_args()
@ -28,6 +34,49 @@ def subcommand_pre_install(_):
['privoxy privoxy/listen-address string [::]:8118'])
def subcommand_setup(_):
"""Setup Privoxy configuration after installing it."""
_restrict_access()
def _load_augeus():
"""Initialize Augeas."""
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
aug.transform('Spacevars', str(PRIVOXY_CONF_PATH))
aug.set('/augeas/context', '/files' + str(PRIVOXY_CONF_PATH))
aug.load()
return aug
def _restrict_access():
"""Make sure Privoxy isn't available over the Internet."""
# https://en.wikipedia.org/wiki/localhost
# https://en.wikipedia.org/wiki/Private_network
# https://en.wikipedia.org/wiki/Link-local_address
# https://en.wikipedia.org/wiki/Unique_local_address
ip_ranges = [
'127.0.0.0/8', # IPv4 loopback address
'10.0.0.0/8', # IPv4 private address
'172.16.0.0/12', # IPv4 private address
'192.168.0.0/16', # IPv4 private address
'169.254.0.0/16', # IPv4 auto-configuration
'[::1]', # IPv4 loopback address
'[fc00::]/7', # IPv6 unique local addresses
'[fe80::]/10', # IPv6 auto-configuration
]
aug = _load_augeus()
for ip_range in ip_ranges:
matches = [
match for match in aug.match('permit-access')
if aug.get(match) == ip_range
]
if not any(matches):
aug.set('permit-access[last() + 1]', ip_range)
aug.save()
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -26,7 +26,8 @@ _description = [
'obnoxious Internet junk. '),
format_lazy(
_('You can use Privoxy by modifying your browser proxy settings to '
'your {box_name} hostname (or IP address) with port 8118. '
'your {box_name} hostname (or IP address) with port 8118. Only '
'connections from local network IP addresses are permitted. '
'While using Privoxy, you can see its configuration details and '
'documentation at '
'<a href="http://config.privoxy.org">http://config.privoxy.org/</a> '
@ -42,7 +43,7 @@ class PrivoxyApp(app_module.App):
app_id = 'privoxy'
_version = 1
_version = 2
def __init__(self):
"""Create components for the app."""
@ -98,6 +99,7 @@ def setup(helper, old_version=None):
"""Install and configure the module."""
helper.call('pre', actions.superuser_run, 'privoxy', ['pre-install'])
app.setup(old_version)
helper.call('post', actions.superuser_run, 'privoxy', ['setup'])
helper.call('post', app.enable)