Ajustes gerais

This commit is contained in:
2025-12-08 07:22:44 -03:00
parent c0681ea6a9
commit 7e529c8460
10 changed files with 630 additions and 111 deletions

View File

@@ -115,8 +115,6 @@
('calendar', '/usr/lib/python3.11/calendar.py', 'PYMODULE'), ('calendar', '/usr/lib/python3.11/calendar.py', 'PYMODULE'),
('urllib.parse', '/usr/lib/python3.11/urllib/parse.py', 'PYMODULE'), ('urllib.parse', '/usr/lib/python3.11/urllib/parse.py', 'PYMODULE'),
('ipaddress', '/usr/lib/python3.11/ipaddress.py', 'PYMODULE'), ('ipaddress', '/usr/lib/python3.11/ipaddress.py', 'PYMODULE'),
('socket', '/usr/lib/python3.11/socket.py', 'PYMODULE'),
('selectors', '/usr/lib/python3.11/selectors.py', 'PYMODULE'),
('quopri', '/usr/lib/python3.11/quopri.py', 'PYMODULE'), ('quopri', '/usr/lib/python3.11/quopri.py', 'PYMODULE'),
('email', '/usr/lib/python3.11/email/__init__.py', 'PYMODULE'), ('email', '/usr/lib/python3.11/email/__init__.py', 'PYMODULE'),
('email.parser', '/usr/lib/python3.11/email/parser.py', 'PYMODULE'), ('email.parser', '/usr/lib/python3.11/email/parser.py', 'PYMODULE'),
@@ -149,12 +147,12 @@
('opcode', '/usr/lib/python3.11/opcode.py', 'PYMODULE'), ('opcode', '/usr/lib/python3.11/opcode.py', 'PYMODULE'),
('ast', '/usr/lib/python3.11/ast.py', 'PYMODULE'), ('ast', '/usr/lib/python3.11/ast.py', 'PYMODULE'),
('stringprep', '/usr/lib/python3.11/stringprep.py', 'PYMODULE'), ('stringprep', '/usr/lib/python3.11/stringprep.py', 'PYMODULE'),
('_py_abc', '/usr/lib/python3.11/_py_abc.py', 'PYMODULE'),
('tracemalloc', '/usr/lib/python3.11/tracemalloc.py', 'PYMODULE'), ('tracemalloc', '/usr/lib/python3.11/tracemalloc.py', 'PYMODULE'),
('pickle', '/usr/lib/python3.11/pickle.py', 'PYMODULE'), ('pickle', '/usr/lib/python3.11/pickle.py', 'PYMODULE'),
('pprint', '/usr/lib/python3.11/pprint.py', 'PYMODULE'), ('pprint', '/usr/lib/python3.11/pprint.py', 'PYMODULE'),
('dataclasses', '/usr/lib/python3.11/dataclasses.py', 'PYMODULE'), ('dataclasses', '/usr/lib/python3.11/dataclasses.py', 'PYMODULE'),
('_compat_pickle', '/usr/lib/python3.11/_compat_pickle.py', 'PYMODULE'), ('_compat_pickle', '/usr/lib/python3.11/_compat_pickle.py', 'PYMODULE'),
('_py_abc', '/usr/lib/python3.11/_py_abc.py', 'PYMODULE'),
('logging.handlers', '/usr/lib/python3.11/logging/handlers.py', 'PYMODULE'), ('logging.handlers', '/usr/lib/python3.11/logging/handlers.py', 'PYMODULE'),
('http.client', '/usr/lib/python3.11/http/client.py', 'PYMODULE'), ('http.client', '/usr/lib/python3.11/http/client.py', 'PYMODULE'),
('ssl', '/usr/lib/python3.11/ssl.py', 'PYMODULE'), ('ssl', '/usr/lib/python3.11/ssl.py', 'PYMODULE'),
@@ -384,6 +382,8 @@
('urllib3.contrib.emscripten.fetch', ('urllib3.contrib.emscripten.fetch',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/urllib3/contrib/emscripten/fetch.py', '/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/urllib3/contrib/emscripten/fetch.py',
'PYMODULE'), 'PYMODULE'),
('socket', '/usr/lib/python3.11/socket.py', 'PYMODULE'),
('selectors', '/usr/lib/python3.11/selectors.py', 'PYMODULE'),
('uuid', '/usr/lib/python3.11/uuid.py', 'PYMODULE'), ('uuid', '/usr/lib/python3.11/uuid.py', 'PYMODULE'),
('subprocess', '/usr/lib/python3.11/subprocess.py', 'PYMODULE'), ('subprocess', '/usr/lib/python3.11/subprocess.py', 'PYMODULE'),
('signal', '/usr/lib/python3.11/signal.py', 'PYMODULE'), ('signal', '/usr/lib/python3.11/signal.py', 'PYMODULE'),
@@ -467,25 +467,17 @@
('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY')], ('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY')],
[], [],
[], [],
[('certifi/py.typed', [('certifi/cacert.pem',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('certifi/cacert.pem',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem', '/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem',
'DATA'), 'DATA'),
('certifi/py.typed',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('base_library.zip', ('base_library.zip',
'/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip', '/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip',
'DATA')], 'DATA')],
[('sre_compile', '/usr/lib/python3.11/sre_compile.py', 'PYMODULE'), [('copyreg', '/usr/lib/python3.11/copyreg.py', 'PYMODULE'),
('traceback', '/usr/lib/python3.11/traceback.py', 'PYMODULE'), ('genericpath', '/usr/lib/python3.11/genericpath.py', 'PYMODULE'),
('_weakrefset', '/usr/lib/python3.11/_weakrefset.py', 'PYMODULE'),
('enum', '/usr/lib/python3.11/enum.py', 'PYMODULE'),
('keyword', '/usr/lib/python3.11/keyword.py', 'PYMODULE'),
('stat', '/usr/lib/python3.11/stat.py', 'PYMODULE'),
('sre_parse', '/usr/lib/python3.11/sre_parse.py', 'PYMODULE'),
('weakref', '/usr/lib/python3.11/weakref.py', 'PYMODULE'),
('linecache', '/usr/lib/python3.11/linecache.py', 'PYMODULE'),
('functools', '/usr/lib/python3.11/functools.py', 'PYMODULE'),
('encodings.zlib_codec', ('encodings.zlib_codec',
'/usr/lib/python3.11/encodings/zlib_codec.py', '/usr/lib/python3.11/encodings/zlib_codec.py',
'PYMODULE'), 'PYMODULE'),
@@ -716,26 +708,34 @@
('encodings.ascii', '/usr/lib/python3.11/encodings/ascii.py', 'PYMODULE'), ('encodings.ascii', '/usr/lib/python3.11/encodings/ascii.py', 'PYMODULE'),
('encodings.aliases', '/usr/lib/python3.11/encodings/aliases.py', 'PYMODULE'), ('encodings.aliases', '/usr/lib/python3.11/encodings/aliases.py', 'PYMODULE'),
('encodings', '/usr/lib/python3.11/encodings/__init__.py', 'PYMODULE'), ('encodings', '/usr/lib/python3.11/encodings/__init__.py', 'PYMODULE'),
('abc', '/usr/lib/python3.11/abc.py', 'PYMODULE'),
('locale', '/usr/lib/python3.11/locale.py', 'PYMODULE'),
('ntpath', '/usr/lib/python3.11/ntpath.py', 'PYMODULE'),
('io', '/usr/lib/python3.11/io.py', 'PYMODULE'),
('reprlib', '/usr/lib/python3.11/reprlib.py', 'PYMODULE'),
('heapq', '/usr/lib/python3.11/heapq.py', 'PYMODULE'),
('sre_constants', '/usr/lib/python3.11/sre_constants.py', 'PYMODULE'),
('collections.abc', '/usr/lib/python3.11/collections/abc.py', 'PYMODULE'),
('collections', '/usr/lib/python3.11/collections/__init__.py', 'PYMODULE'),
('posixpath', '/usr/lib/python3.11/posixpath.py', 'PYMODULE'),
('_collections_abc', '/usr/lib/python3.11/_collections_abc.py', 'PYMODULE'), ('_collections_abc', '/usr/lib/python3.11/_collections_abc.py', 'PYMODULE'),
('codecs', '/usr/lib/python3.11/codecs.py', 'PYMODULE'), ('traceback', '/usr/lib/python3.11/traceback.py', 'PYMODULE'),
('types', '/usr/lib/python3.11/types.py', 'PYMODULE'),
('warnings', '/usr/lib/python3.11/warnings.py', 'PYMODULE'),
('keyword', '/usr/lib/python3.11/keyword.py', 'PYMODULE'),
('posixpath', '/usr/lib/python3.11/posixpath.py', 'PYMODULE'),
('_weakrefset', '/usr/lib/python3.11/_weakrefset.py', 'PYMODULE'),
('stat', '/usr/lib/python3.11/stat.py', 'PYMODULE'),
('sre_compile', '/usr/lib/python3.11/sre_compile.py', 'PYMODULE'),
('sre_constants', '/usr/lib/python3.11/sre_constants.py', 'PYMODULE'),
('heapq', '/usr/lib/python3.11/heapq.py', 'PYMODULE'),
('operator', '/usr/lib/python3.11/operator.py', 'PYMODULE'), ('operator', '/usr/lib/python3.11/operator.py', 'PYMODULE'),
('copyreg', '/usr/lib/python3.11/copyreg.py', 'PYMODULE'),
('re._parser', '/usr/lib/python3.11/re/_parser.py', 'PYMODULE'), ('re._parser', '/usr/lib/python3.11/re/_parser.py', 'PYMODULE'),
('re._constants', '/usr/lib/python3.11/re/_constants.py', 'PYMODULE'), ('re._constants', '/usr/lib/python3.11/re/_constants.py', 'PYMODULE'),
('re._compiler', '/usr/lib/python3.11/re/_compiler.py', 'PYMODULE'), ('re._compiler', '/usr/lib/python3.11/re/_compiler.py', 'PYMODULE'),
('re._casefix', '/usr/lib/python3.11/re/_casefix.py', 'PYMODULE'), ('re._casefix', '/usr/lib/python3.11/re/_casefix.py', 'PYMODULE'),
('re', '/usr/lib/python3.11/re/__init__.py', 'PYMODULE'), ('re', '/usr/lib/python3.11/re/__init__.py', 'PYMODULE'),
('genericpath', '/usr/lib/python3.11/genericpath.py', 'PYMODULE'), ('functools', '/usr/lib/python3.11/functools.py', 'PYMODULE'),
('types', '/usr/lib/python3.11/types.py', 'PYMODULE'), ('sre_parse', '/usr/lib/python3.11/sre_parse.py', 'PYMODULE'),
('warnings', '/usr/lib/python3.11/warnings.py', 'PYMODULE'), ('weakref', '/usr/lib/python3.11/weakref.py', 'PYMODULE'),
('collections.abc', '/usr/lib/python3.11/collections/abc.py', 'PYMODULE'),
('collections', '/usr/lib/python3.11/collections/__init__.py', 'PYMODULE'),
('locale', '/usr/lib/python3.11/locale.py', 'PYMODULE'),
('enum', '/usr/lib/python3.11/enum.py', 'PYMODULE'),
('io', '/usr/lib/python3.11/io.py', 'PYMODULE'),
('codecs', '/usr/lib/python3.11/codecs.py', 'PYMODULE'),
('ntpath', '/usr/lib/python3.11/ntpath.py', 'PYMODULE'),
('abc', '/usr/lib/python3.11/abc.py', 'PYMODULE'),
('reprlib', '/usr/lib/python3.11/reprlib.py', 'PYMODULE'),
('linecache', '/usr/lib/python3.11/linecache.py', 'PYMODULE'),
('os', '/usr/lib/python3.11/os.py', 'PYMODULE')]) ('os', '/usr/lib/python3.11/os.py', 'PYMODULE')])

View File

@@ -109,19 +109,19 @@
('libbz2.so.1.0', '/lib/x86_64-linux-gnu/libbz2.so.1.0', 'BINARY'), ('libbz2.so.1.0', '/lib/x86_64-linux-gnu/libbz2.so.1.0', 'BINARY'),
('libssl.so.3', '/lib/x86_64-linux-gnu/libssl.so.3', 'BINARY'), ('libssl.so.3', '/lib/x86_64-linux-gnu/libssl.so.3', 'BINARY'),
('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY'), ('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY'),
('certifi/py.typed',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('certifi/cacert.pem', ('certifi/cacert.pem',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem', '/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem',
'DATA'), 'DATA'),
('certifi/py.typed',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('base_library.zip', ('base_library.zip',
'/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip', '/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip',
'DATA')], 'DATA')],
[], [],
False, False,
False, False,
1765065952, 1765128812,
[('run', [('run',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run', '/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run',
'EXECUTABLE')], 'EXECUTABLE')],

View File

@@ -104,12 +104,12 @@
('libbz2.so.1.0', '/lib/x86_64-linux-gnu/libbz2.so.1.0', 'BINARY'), ('libbz2.so.1.0', '/lib/x86_64-linux-gnu/libbz2.so.1.0', 'BINARY'),
('libssl.so.3', '/lib/x86_64-linux-gnu/libssl.so.3', 'BINARY'), ('libssl.so.3', '/lib/x86_64-linux-gnu/libssl.so.3', 'BINARY'),
('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY'), ('libuuid.so.1', '/lib/x86_64-linux-gnu/libuuid.so.1', 'BINARY'),
('certifi/py.typed',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('certifi/cacert.pem', ('certifi/cacert.pem',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem', '/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/cacert.pem',
'DATA'), 'DATA'),
('certifi/py.typed',
'/home/halbebruno/Projetos/DNSBlock/agent/build_venv/lib/python3.11/site-packages/certifi/py.typed',
'DATA'),
('base_library.zip', ('base_library.zip',
'/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip', '/home/halbebruno/Projetos/DNSBlock/agent/build/dnsblock-agent/base_library.zip',
'DATA')], 'DATA')],

View File

@@ -151,6 +151,7 @@ imports:
&#8226; <a href="#enum">enum</a> &#8226; <a href="#enum">enum</a>
&#8226; <a href="#functools">functools</a> &#8226; <a href="#functools">functools</a>
&#8226; <a href="#genericpath">genericpath</a> &#8226; <a href="#genericpath">genericpath</a>
&#8226; <a href="#grp">grp</a>
&#8226; <a href="#heapq">heapq</a> &#8226; <a href="#heapq">heapq</a>
&#8226; <a href="#io">io</a> &#8226; <a href="#io">io</a>
&#8226; <a href="#json">json</a> &#8226; <a href="#json">json</a>
@@ -163,6 +164,7 @@ imports:
&#8226; <a href="#operator">operator</a> &#8226; <a href="#operator">operator</a>
&#8226; <a href="#os">os</a> &#8226; <a href="#os">os</a>
&#8226; <a href="#posixpath">posixpath</a> &#8226; <a href="#posixpath">posixpath</a>
&#8226; <a href="#pwd">pwd</a>
&#8226; <a href="#pyi_rth_inspect.py">pyi_rth_inspect.py</a> &#8226; <a href="#pyi_rth_inspect.py">pyi_rth_inspect.py</a>
&#8226; <a href="#re">re</a> &#8226; <a href="#re">re</a>
&#8226; <a href="#re._casefix">re._casefix</a> &#8226; <a href="#re._casefix">re._casefix</a>
@@ -171,6 +173,7 @@ imports:
&#8226; <a href="#re._parser">re._parser</a> &#8226; <a href="#re._parser">re._parser</a>
&#8226; <a href="#reprlib">reprlib</a> &#8226; <a href="#reprlib">reprlib</a>
&#8226; <a href="#requests">requests</a> &#8226; <a href="#requests">requests</a>
&#8226; <a href="#socket">socket</a>
&#8226; <a href="#sre_compile">sre_compile</a> &#8226; <a href="#sre_compile">sre_compile</a>
&#8226; <a href="#sre_constants">sre_constants</a> &#8226; <a href="#sre_constants">sre_constants</a>
&#8226; <a href="#sre_parse">sre_parse</a> &#8226; <a href="#sre_parse">sre_parse</a>
@@ -5517,7 +5520,8 @@ imported by:
<a name="grp"></a> <a name="grp"></a>
<tt>grp</tt> <span class="moduletype"><i>(builtin module)</i></span> <div class="import"> <tt>grp</tt> <span class="moduletype"><i>(builtin module)</i></span> <div class="import">
imported by: imported by:
<a href="#pathlib">pathlib</a> <a href="#main.py">main.py</a>
&#8226; <a href="#pathlib">pathlib</a>
&#8226; <a href="#shutil">shutil</a> &#8226; <a href="#shutil">shutil</a>
&#8226; <a href="#subprocess">subprocess</a> &#8226; <a href="#subprocess">subprocess</a>
&#8226; <a href="#tarfile">tarfile</a> &#8226; <a href="#tarfile">tarfile</a>
@@ -7274,6 +7278,7 @@ imported by:
<tt>pwd</tt> <span class="moduletype"><i>(builtin module)</i></span> <div class="import"> <tt>pwd</tt> <span class="moduletype"><i>(builtin module)</i></span> <div class="import">
imported by: imported by:
<a href="#getpass">getpass</a> <a href="#getpass">getpass</a>
&#8226; <a href="#main.py">main.py</a>
&#8226; <a href="#netrc">netrc</a> &#8226; <a href="#netrc">netrc</a>
&#8226; <a href="#pathlib">pathlib</a> &#8226; <a href="#pathlib">pathlib</a>
&#8226; <a href="#posixpath">posixpath</a> &#8226; <a href="#posixpath">posixpath</a>
@@ -8230,6 +8235,7 @@ imported by:
&#8226; <a href="#ftplib">ftplib</a> &#8226; <a href="#ftplib">ftplib</a>
&#8226; <a href="#http.client">http.client</a> &#8226; <a href="#http.client">http.client</a>
&#8226; <a href="#logging.handlers">logging.handlers</a> &#8226; <a href="#logging.handlers">logging.handlers</a>
&#8226; <a href="#main.py">main.py</a>
&#8226; <a href="#platform">platform</a> &#8226; <a href="#platform">platform</a>
&#8226; <a href="#requests.adapters">requests.adapters</a> &#8226; <a href="#requests.adapters">requests.adapters</a>
&#8226; <a href="#requests.utils">requests.utils</a> &#8226; <a href="#requests.utils">requests.utils</a>

View File

@@ -1,6 +1,7 @@
{ {
"serial_key": "YOUR_SERIAL_KEY_HERE", "serial_key": "SUA_CHAVE_SERIAL_AQUI",
"api_url": "https://app.dnsblock.com.br", "api_url": "https://app.dnsblock.com.br",
"rpz_file": "/etc/unbound/rpz.zones/rpz.dnsblock.zone", "rpz_file": "/opt/dnsblock/rpz/rpz.dnsblock.zone",
"reload_command": "systemctl reload unbound" "reload_command": "systemctl reload unbound",
"file_owner": "unbound:unbound"
} }

View File

@@ -3,17 +3,17 @@ import sys
import time import time
import json import json
import uuid import uuid
import socket
import pwd
import grp
import requests import requests
import logging import logging
from datetime import datetime from datetime import datetime
# Configuration
CONFIG_FILE = '/opt/dnsblock/config.json'
import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
# Configuration # Configuration
CONFIG_FILE = '/opt/dnsblock/config.json' CONFIG_FILE = '/opt/dnsblock/config.json'
STATE_FILE = '/opt/dnsblock/rpz_state.json'
LOG_DIR = '/opt/dnsblock/logs' LOG_DIR = '/opt/dnsblock/logs'
LOG_FILE = os.path.join(LOG_DIR, 'agent.log') LOG_FILE = os.path.join(LOG_DIR, 'agent.log')
RPZ_FILE_DEFAULT = '/opt/dnsblock/rpz.dnsblock.zone' RPZ_FILE_DEFAULT = '/opt/dnsblock/rpz.dnsblock.zone'
@@ -66,32 +66,142 @@ def load_config():
logging.error(f"Error loading config: {e}") logging.error(f"Error loading config: {e}")
sys.exit(1) sys.exit(1)
def generate_rpz(domains, output_file): def get_system_domain():
"""Generates the RPZ zone file.""" """Detects the system domain from FQDN or hostname."""
try:
fqdn = socket.getfqdn()
if fqdn and '.' in fqdn:
# Extract domain portion (e.g., server.gtecnet.com.br -> gtecnet.com.br)
parts = fqdn.split('.')
if len(parts) >= 2:
domain = '.'.join(parts[1:])
logging.info(f"Detected system domain: {domain}")
return domain
# Try hostname as fallback
hostname = socket.gethostname()
if hostname and '.' in hostname:
parts = hostname.split('.')
if len(parts) >= 2:
domain = '.'.join(parts[1:])
logging.info(f"Detected system domain from hostname: {domain}")
return domain
logging.info("Could not detect system domain, using localhost")
return "localhost"
except Exception as e:
logging.warning(f"Error detecting system domain: {e}, using localhost")
return "localhost"
def load_rpz_state():
"""Loads RPZ state from JSON file."""
if not os.path.exists(STATE_FILE):
return {'last_serial': None, 'last_date': None}
try:
with open(STATE_FILE, 'r') as f:
return json.load(f)
except Exception as e:
logging.warning(f"Error loading RPZ state: {e}")
return {'last_serial': None, 'last_date': None}
def save_rpz_state(state):
"""Saves RPZ state to JSON file."""
try:
with open(STATE_FILE, 'w') as f:
json.dump(state, f)
except Exception as e:
logging.error(f"Error saving RPZ state: {e}")
def generate_serial():
"""Generates serial in YYYYMMDDNN format."""
today = datetime.now().strftime('%Y%m%d')
state = load_rpz_state()
last_serial = state.get('last_serial')
last_date = state.get('last_date')
if last_date == today and last_serial:
# Same day, increment sequence
sequence = int(str(last_serial)[-2:]) + 1
if sequence > 99:
sequence = 99 # Cap at 99
else:
# New day, reset sequence
sequence = 0
new_serial = int(f"{today}{sequence:02d}")
# Save state
save_rpz_state({'last_serial': new_serial, 'last_date': today})
return new_serial
def apply_file_ownership(path, file_owner):
"""Apply user:group ownership to a file or directory."""
if not file_owner:
return True
try:
parts = file_owner.split(':')
user = parts[0]
group = parts[1] if len(parts) > 1 else user
uid = pwd.getpwnam(user).pw_uid
gid = grp.getgrnam(group).gr_gid
os.chown(path, uid, gid)
logging.debug(f"Applied ownership {file_owner} to {path}")
return True
except KeyError as e:
logging.warning(f"User or group not found for file_owner '{file_owner}': {e}")
return False
except PermissionError as e:
logging.warning(f"Permission denied setting ownership on {path}: {e}")
return False
except Exception as e:
logging.error(f"Error applying ownership to {path}: {e}")
return False
def generate_rpz(domains, output_file, file_owner=None):
"""Generates the RPZ zone file with proper SOA header."""
try: try:
# Ensure directory exists # Ensure directory exists
os.makedirs(os.path.dirname(output_file), exist_ok=True) output_dir = os.path.dirname(output_file)
if output_dir:
os.makedirs(output_dir, exist_ok=True)
# Apply ownership to directory
if file_owner:
apply_file_ownership(output_dir, file_owner)
# Get system domain and generate serial
system_domain = get_system_domain()
serial = generate_serial()
with open(output_file, 'w') as f: with open(output_file, 'w') as f:
f.write("$TTL 30\n") f.write("$TTL 1H\n")
f.write("@ IN SOA rpz.dnsblock.zone. root.rpz.dnsblock.zone. (\n") f.write(f"@ IN SOA localhost. {system_domain}. (\n")
f.write(f" {int(time.time())} ; Serial\n") f.write(f" {serial} ; Serial\n")
f.write(" 30 ; Refresh\n") f.write(" 1h ; Refresh\n")
f.write(" 15 ; Retry\n") f.write(" 15m ; Retry\n")
f.write(" 604800 ; Expire\n") f.write(" 30d ; Expire\n")
f.write(" 30 ) ; Negative Cache TTL\n") f.write(" 2h ; Negative Cache TTL\n")
f.write(";\n") f.write(" )\n")
f.write("@ IN NS localhost.\n") f.write(f" NS {system_domain}.\n")
f.write("@ IN A 127.0.0.1\n") f.write("\n")
f.write(";\n") f.write("; RPZ block hosts\n")
f.write("; Blocked Domains\n") f.write("\n")
for domain in domains: for domain in domains:
# CNAME to . (NXDOMAIN) or specific sinkhole # CNAME to . (NXDOMAIN) or specific sinkhole
f.write(f"{domain} CNAME .\n") f.write(f"{domain} CNAME .\n")
f.write(f"*.{domain} CNAME .\n") f.write(f"*.{domain} CNAME .\n")
logging.info(f"RPZ file generated at {output_file} with {len(domains)} domains.") # Apply ownership to file
if file_owner:
apply_file_ownership(output_file, file_owner)
logging.info(f"RPZ file generated at {output_file} with {len(domains)} domains (serial: {serial}).")
return True return True
except Exception as e: except Exception as e:
logging.error(f"Error generating RPZ: {e}") logging.error(f"Error generating RPZ: {e}")
@@ -106,6 +216,7 @@ def main():
api_url = config.get('api_url') api_url = config.get('api_url')
rpz_file = config.get('rpz_file', RPZ_FILE_DEFAULT) rpz_file = config.get('rpz_file', RPZ_FILE_DEFAULT)
reload_command = config.get('reload_command') reload_command = config.get('reload_command')
file_owner = config.get('file_owner') # Ex: 'unbound:unbound'
if not serial_key or not api_url: if not serial_key or not api_url:
logging.error("Missing serial_key or api_url in config.") logging.error("Missing serial_key or api_url in config.")
@@ -140,7 +251,7 @@ def main():
if current_checksum != last_checksum: if current_checksum != last_checksum:
logging.info("Change detected in domain list. Updating RPZ...") logging.info("Change detected in domain list. Updating RPZ...")
domains = data.get('domains', []) domains = data.get('domains', [])
if generate_rpz(domains, rpz_file): if generate_rpz(domains, rpz_file, file_owner):
last_checksum = current_checksum last_checksum = current_checksum
if reload_command: if reload_command:

View File

@@ -1,58 +1,459 @@
#!/bin/bash #!/bin/bash
# DNSBlock Agent Installer (Binary Distribution) # ============================================================================
# DNSBlock Agent - Script de Instalação e Desinstalação
# ============================================================================
# Este script realiza a instalação ou desinstalação completa do DNSBlock Agent
# Requer privilégios de root para execução
#
# Uso:
# ./install.sh Instalação interativa
# ./install.sh uninstall Desinstalação
# ============================================================================
set -e
# Diretórios e arquivos
INSTALL_DIR="/opt/dnsblock" INSTALL_DIR="/opt/dnsblock"
SOURCE_DIR=$(pwd) RPZ_DIR="$INSTALL_DIR/rpz"
SERVICE_FILE="/etc/systemd/system/dnsblock-agent.service"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Check root # Configurações do Unbound
if [ "$(id -u)" -ne 0 ]; then UNBOUND_CONF_DIR="/etc/unbound/unbound.conf.d"
echo "Please run as root" UNBOUND_MAIN_CONF="/etc/unbound/unbound.conf"
DNSBLOCK_CONF="$UNBOUND_CONF_DIR/dnsblock.conf"
DNSBLOCK_INCLUDE='include: "/etc/unbound/unbound.conf.d/dnsblock.conf"'
# Variáveis globais
SERIAL=""
NO_SERIAL=false
# ============================================================================
# FUNÇÕES UTILITÁRIAS
# ============================================================================
# Verificar se está executando como root
verificar_root() {
if [ "$(id -u)" -ne 0 ]; then
whiptail --title "Erro" --msgbox "Este script deve ser executado como root.\n\nExecute novamente com sudo." 10 50
exit 1 exit 1
fi
echo "Installing DNSBlock Agent..."
# Create Directory
mkdir -p "$INSTALL_DIR"
# Copy Binary
if [ -f "$SOURCE_DIR/dnsblock-agent" ]; then
cp "$SOURCE_DIR/dnsblock-agent" "$INSTALL_DIR/"
chmod +x "$INSTALL_DIR/dnsblock-agent"
else
echo "Error: dnsblock-agent binary not found in current directory."
exit 1
fi
# Create Config if not exists
if [ ! -f "$INSTALL_DIR/config.json" ]; then
echo "Creating default config..."
if [ -f "$SOURCE_DIR/config.json.example" ]; then
cp "$SOURCE_DIR/config.json.example" "$INSTALL_DIR/config.json"
else
cat <<EOF > "$INSTALL_DIR/config.json"
{
"serial_key": "YOUR_SERIAL_KEY_HERE",
"api_url": "https://seu-painel.com",
"rpz_file": "/opt/dnsblock/rpz.dnsblock.zone"
}
EOF
fi fi
echo "Config file created at $INSTALL_DIR/config.json. Please edit it with your Serial Key and API URL." }
fi
# Setup Systemd Service # Verificar dependências
echo "Setting up systemd service..." verificar_dependencias() {
if [ -f "$SOURCE_DIR/dnsblock-agent.service" ]; then local deps_faltando=""
cp "$SOURCE_DIR/dnsblock-agent.service" /etc/systemd/system/
if ! command -v whiptail &> /dev/null; then
echo "Erro: whiptail não encontrado. Instale-o antes de continuar."
exit 1
fi
if ! command -v tar &> /dev/null; then
deps_faltando="$deps_faltando tar"
fi
if ! command -v unbound-checkconf &> /dev/null; then
deps_faltando="$deps_faltando unbound-checkconf"
fi
if [ -n "$deps_faltando" ]; then
whiptail --title "Dependências Faltando" \
--msgbox "As seguintes dependências não foram encontradas:\n$deps_faltando\n\nPor favor, instale-as antes de continuar." 12 55
exit 1
fi
}
# ============================================================================
# FUNÇÕES DE SERIAL
# ============================================================================
# Solicitar o serial via whiptail
solicitar_serial() {
local serial=""
serial=$(whiptail --title "DNSBlock Agent - Ativação" \
--inputbox "Digite o serial de ativação do agente:\n\n(Deixe em branco para instalar sem serial)" \
12 60 3>&1 1>&2 2>&3)
local status=$?
if [ $status -ne 0 ]; then
# Usuário cancelou com ESC ou Cancel
whiptail --title "Instalação Cancelada" \
--msgbox "A instalação foi cancelada pelo usuário." 8 45
exit 0
fi
if [ -z "$serial" ]; then
# Serial em branco - perguntar se deseja continuar
if whiptail --title "Instalação sem Serial" \
--yesno "Você não informou um serial.\n\nDeseja instalar sem serial?\n\n(O serviço será ativado mas não inicializado)\n\nVocê pode obter seu serial em:\nhttp://painel.dnsblock.com.br" \
14 55; then
NO_SERIAL=true
echo ""
else
whiptail --title "Instalação Cancelada" \
--msgbox "A instalação foi cancelada pelo usuário." 8 45
exit 0
fi
else
echo "$serial"
fi
}
# Atualizar o serial no config.json
atualizar_config_serial() {
local serial="$1"
local config_file="$INSTALL_DIR/config.json"
if [ -f "$config_file" ]; then
sed -i "s/\"serial_key\":[[:space:]]*\"[^\"]*\"/\"serial_key\": \"$serial\"/" "$config_file"
fi
}
# ============================================================================
# FUNÇÕES DE CONFIGURAÇÃO DO UNBOUND
# ============================================================================
# Encontrar o arquivo de configuração apropriado do Unbound
encontrar_arquivo_config_unbound() {
local config_file=""
# Verificar se existe algum arquivo com configuração RPZ
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
if [ -f "$conf" ] && grep -q "rpz:" "$conf" 2>/dev/null; then
config_file="$conf"
break
fi
done
# Se não encontrou arquivo com RPZ, usar local.conf se existir
if [ -z "$config_file" ]; then
if [ -f "$UNBOUND_CONF_DIR/local.conf" ]; then
config_file="$UNBOUND_CONF_DIR/local.conf"
elif [ -f "$UNBOUND_MAIN_CONF" ]; then
config_file="$UNBOUND_MAIN_CONF"
fi
fi
echo "$config_file"
}
# Verificar se o include já existe
verificar_include_existente() {
local include_pattern='include:[[:space:]]*"/etc/unbound/unbound.conf.d/dnsblock.conf"'
if [ -f "$UNBOUND_MAIN_CONF" ] && grep -qE "$include_pattern" "$UNBOUND_MAIN_CONF" 2>/dev/null; then
return 0
fi
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
if [ -f "$conf" ] && grep -qE "$include_pattern" "$conf" 2>/dev/null; then
return 0
fi
done
return 1
}
# Configurar o Unbound para usar o DNSBlock
configurar_unbound() {
# Criar diretório de configuração do Unbound se não existir
if [ ! -d "$UNBOUND_CONF_DIR" ]; then
mkdir -p "$UNBOUND_CONF_DIR"
chown unbound:unbound "$UNBOUND_CONF_DIR"
fi
# Criar o diretório RPZ
mkdir -p "$RPZ_DIR"
chown unbound:unbound "$RPZ_DIR"
# Criar arquivo de configuração do DNSBlock para o Unbound
cat > "$DNSBLOCK_CONF" << 'EOF'
rpz:
name: rpz.dnsblock.zone
zonefile: /opt/dnsblock/rpz/rpz.dnsblock.zone
rpz-action-override: nxdomain
EOF
chown unbound:unbound "$DNSBLOCK_CONF"
chmod 644 "$DNSBLOCK_CONF"
# Adicionar include se não existir
if ! verificar_include_existente; then
local config_file=$(encontrar_arquivo_config_unbound)
if [ -z "$config_file" ]; then
return 1
fi
if grep -q "rpz:" "$config_file" 2>/dev/null; then
sed -i "/rpz:/i # DNSBlock\n$DNSBLOCK_INCLUDE\n" "$config_file"
else
echo "" >> "$config_file"
echo "# DNSBlock" >> "$config_file"
echo "$DNSBLOCK_INCLUDE" >> "$config_file"
fi
fi
# Criar arquivo RPZ vazio se não existir
local rpz_file="$RPZ_DIR/rpz.dnsblock.zone"
if [ ! -f "$rpz_file" ]; then
cat > "$rpz_file" << 'EOF'
$TTL 1H
@ SOA localhost. hostmaster.localhost. (
1 ; Serial
1h ; Refresh
15m ; Retry
30d ; Expire
2h ; Negative Cache TTL
)
NS localhost.
; RPZ block hosts
EOF
chown unbound:unbound "$rpz_file"
chmod 644 "$rpz_file"
fi
# Verificar configuração do Unbound
if ! unbound-checkconf &>/dev/null; then
rm -f "$DNSBLOCK_CONF"
remover_include_unbound
return 1
fi
# Reiniciar o Unbound
systemctl restart unbound 2>/dev/null || true
return 0
}
# Remover o include do DNSBlock dos arquivos de configuração
remover_include_unbound() {
local include_pattern='include:[[:space:]]*"/etc/unbound/unbound.conf.d/dnsblock.conf"'
local comment_pattern='#[[:space:]]*DNSBlock'
if [ -f "$UNBOUND_MAIN_CONF" ]; then
sed -i "/$include_pattern/d" "$UNBOUND_MAIN_CONF"
sed -i "/$comment_pattern/d" "$UNBOUND_MAIN_CONF"
fi
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
if [ -f "$conf" ] && [ "$conf" != "$DNSBLOCK_CONF" ]; then
sed -i "/$include_pattern/d" "$conf"
sed -i "/$comment_pattern/d" "$conf"
fi
done
}
# Remover configuração do Unbound
remover_configuracao_unbound() {
remover_include_unbound
if [ -f "$DNSBLOCK_CONF" ]; then
rm -f "$DNSBLOCK_CONF"
fi
if unbound-checkconf &>/dev/null; then
systemctl restart unbound 2>/dev/null || true
fi
}
# ============================================================================
# FUNÇÃO DE INSTALAÇÃO
# ============================================================================
instalar() {
# Verificar dependências
verificar_dependencias
# Verificar se já está instalado
if [ -d "$INSTALL_DIR" ]; then
if ! whiptail --title "DNSBlock já instalado" \
--yesno "O DNSBlock Agent já está instalado.\n\nDeseja reinstalar?" 10 50; then
exit 0
fi
# Parar serviço se estiver rodando
systemctl stop dnsblock-agent 2>/dev/null || true
systemctl disable dnsblock-agent 2>/dev/null || true
rm -rf "$INSTALL_DIR"
fi
# Solicitar serial
SERIAL=$(solicitar_serial)
# Exibir progresso
{
echo "10"; echo "# Criando diretórios..."
mkdir -p "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/logs"
mkdir -p "$INSTALL_DIR/rpz"
sleep 0.3
echo "30"; echo "# Copiando arquivos..."
# Copiar todos os arquivos exceto o service file e o próprio install.sh
for item in "$SCRIPT_DIR"/*; do
local basename=$(basename "$item")
if [ "$basename" != "dnsblock-agent.service" ] && [ "$basename" != "install.sh" ]; then
cp -r "$item" "$INSTALL_DIR/"
fi
done
sleep 0.3
echo "50"; echo "# Configurando permissões..."
chmod +x "$INSTALL_DIR/dnsblock-agent" 2>/dev/null || true
touch "$INSTALL_DIR/logs/agent.log"
chown -R unbound:unbound "$INSTALL_DIR"
chmod 755 "$INSTALL_DIR"
sleep 0.3
echo "60"; echo "# Configurando serial..."
if [ -n "$SERIAL" ]; then
atualizar_config_serial "$SERIAL"
fi
sleep 0.3
echo "70"; echo "# Instalando serviço..."
if [ -f "$SCRIPT_DIR/dnsblock-agent.service" ]; then
mv "$SCRIPT_DIR/dnsblock-agent.service" "$SERVICE_FILE"
fi
systemctl daemon-reload systemctl daemon-reload
systemctl enable dnsblock-agent systemctl enable dnsblock-agent
sleep 0.3
echo "Installation Complete!" echo "85"; echo "# Configurando Unbound..."
echo "1. Edit /opt/dnsblock/config.json" configurar_unbound || true
echo "2. Start service: systemctl start dnsblock-agent" sleep 0.3
else
echo "Error: dnsblock-agent.service not found." echo "95"; echo "# Finalizando..."
if [ -n "$SERIAL" ]; then
systemctl start dnsblock-agent
fi
sleep 0.3
echo "100"; echo "# Concluído!"
} | whiptail --title "DNSBlock Agent - Instalação" --gauge "Iniciando instalação..." 8 60 0
# Exibir mensagem final
if [ -n "$SERIAL" ]; then
whiptail --title "Instalação Concluída" \
--msgbox "O DNSBlock Agent foi instalado e iniciado com sucesso!\n\nComandos úteis:\n • Status: systemctl status dnsblock-agent\n • Logs: journalctl -u dnsblock-agent -f\n • Reiniciar: systemctl restart dnsblock-agent" 14 60
else
whiptail --title "Instalação Concluída (sem serial)" \
--msgbox "O DNSBlock Agent foi instalado mas NÃO foi iniciado.\n\nPara ativar o agente:\n\n1. Obtenha seu serial em:\n http://painel.dnsblock.com.br\n\n2. Edite o arquivo:\n $INSTALL_DIR/config.json\n\n3. Inicie o serviço:\n systemctl start dnsblock-agent" 18 60
fi
}
# ============================================================================
# FUNÇÃO DE DESINSTALAÇÃO
# ============================================================================
desinstalar() {
if [ ! -d "$INSTALL_DIR" ] && [ ! -f "$SERVICE_FILE" ] && [ ! -f "$DNSBLOCK_CONF" ]; then
whiptail --title "Não Instalado" \
--msgbox "O DNSBlock Agent não parece estar instalado." 8 50
exit 0
fi
if ! whiptail --title "Confirmar Desinstalação" \
--yesno "Você está prestes a desinstalar o DNSBlock Agent.\n\nTodos os arquivos e configurações serão removidos.\n\nDeseja continuar?" 12 55; then
exit 0
fi
# Exibir progresso
{
echo "10"; echo "# Parando serviço..."
systemctl stop dnsblock-agent 2>/dev/null || true
sleep 0.3
echo "30"; echo "# Desabilitando serviço..."
systemctl disable dnsblock-agent 2>/dev/null || true
sleep 0.3
echo "50"; echo "# Removendo arquivo de serviço..."
rm -f "$SERVICE_FILE"
systemctl daemon-reload
sleep 0.3
echo "70"; echo "# Removendo configuração do Unbound..."
remover_configuracao_unbound
sleep 0.3
echo "90"; echo "# Removendo arquivos..."
rm -rf "$INSTALL_DIR"
sleep 0.3
echo "100"; echo "# Concluído!"
} | whiptail --title "DNSBlock Agent - Desinstalação" --gauge "Removendo DNSBlock Agent..." 8 60 0
whiptail --title "Desinstalação Concluída" \
--msgbox "O DNSBlock Agent foi completamente removido do sistema." 8 55
}
# ============================================================================
# MENU PRINCIPAL
# ============================================================================
menu_principal() {
local opcao
opcao=$(whiptail --title "DNSBlock Agent" \
--menu "Selecione uma opção:" 15 60 4 \
"1" "Instalar DNSBlock Agent" \
"2" "Desinstalar DNSBlock Agent" \
"3" "Sair" \
3>&1 1>&2 2>&3)
local status=$?
if [ $status -ne 0 ] || [ "$opcao" = "3" ]; then
exit 0
fi
case "$opcao" in
1) instalar ;;
2) desinstalar ;;
esac
}
# ============================================================================
# INÍCIO DO SCRIPT
# ============================================================================
# Verificar root
verificar_root
# Processar argumentos
case "${1:-}" in
install)
instalar
;;
uninstall|remove)
desinstalar
;;
--help|-h)
echo ""
echo "DNSBlock Agent - Script de Instalação"
echo ""
echo "Uso: $0 [install|uninstall]"
echo ""
echo "Opções:"
echo " install Instalar o DNSBlock Agent"
echo " uninstall Desinstalar o DNSBlock Agent"
echo " --help Exibir esta mensagem"
echo ""
echo "Se executado sem argumentos, exibe o menu interativo."
echo ""
;;
"")
menu_principal
;;
*)
echo "Opção inválida: $1"
echo "Use --help para ver as opções disponíveis."
exit 1 exit 1
fi ;;
esac