Metadata-Version: 2.4
Name: netbox-plugin-dns-bridge
Version: 1.5.7
Summary: A bridge between netbox-plugin-dns and your DNS infrastructure.
Author: Sven Luethi
License: MIT License
        
        Copyright (c) 2025-2026 Sven Luethi
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
        associated documentation files (the “Software”), to deal in the Software without restriction,
        including without limitation the rights to use, copy, modify, merge, publish, distribute,
        sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or substantial
        portions of the Software.
        
        THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
        NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
        NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
        OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
        CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        
Project-URL: Homepage, https://github.com/Suraxius/netbox-plugin-bind-provisioner
Project-URL: Issues, https://github.com/Suraxius/netbox-plugin-bind-provisioner/issues
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: netbox-plugin-dns>=1.5.0
Requires-Dist: dnspython>=2.8.0
Dynamic: license-file

# NetBox DNS Bridge

The NetBox DNS Bridge plugin extends [NetBox DNS](https://github.com/sys4/netbox-plugin-dns) by
embedding a lightweight DNS server directly within NetBox. It acts as a bridge between NetBox DNS
and your existing DNS infrastructure, leveraging native DNS mechanisms for seamless integration.
These include zone transfers (RFC 5936), catalog zones (RFC 9432), and notifying clients about zone
changes (RFC 1996).

<a href="https://pypi.org/project/netbox-plugin-dns-bridge/"><img src="https://img.shields.io/pypi/v/netbox-plugin-dns-bridge" alt="PyPi"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/stargazers"><img src="https://img.shields.io/github/stars/suraxius/netbox-plugin-dns-bridge?style=flat" alt="Stars Badge"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/network/members"><img src="https://img.shields.io/github/forks/suraxius/netbox-plugin-dns-bridge?style=flat" alt="Forks Badge"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/issues"><img src="https://img.shields.io/github/issues/suraxius/netbox-plugin-dns-bridge" alt="Issues Badge"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/pulls"><img src="https://img.shields.io/github/issues-pr/suraxius/netbox-plugin-dns-bridge" alt="Pull Requests Badge"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/graphs/contributors"><img src="https://img.shields.io/github/contributors/suraxius/netbox-plugin-dns-bridge?color=2b9348" alt="GitHub contributors"></a>
<a href="https://github.com/suraxius/netbox-plugin-dns-bridge/blob/master/LICENSE"><img src="https://img.shields.io/github/license/suraxius/netbox-plugin-dns-bridge?color=2b9348" alt="License Badge"></a>
<a href="https://github.com/psf/black"><img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code Style Black"></a>
<a href="https://pepy.tech/project/netbox-plugin-dns-bridge"><img src="https://static.pepy.tech/personalized-badge/netbox-plugin-dns-bridge?period=total&left_color=BLACK&right_color=BLUE&left_text=Downloads" alt="Downloads"></a>
<a href="https://pepy.tech/project/netbox-plugin-dns-bridge"><img src="https://static.pepy.tech/personalized-badge/netbox-plugin-dns-bridge?period=monthly&left_color=BLACK&right_color=BLUE&left_text=Downloads%2fMonth" alt="Downloads/Month"></a>
<a href="https://pepy.tech/project/netbox-plugin-dns-bridge"><img src="https://static.pepy.tech/personalized-badge/netbox-plugin-dns-bridge?period=weekly&left_color=BLACK&right_color=BLUE&left_text=Downloads%2fWeek" alt="Downloads/Week"></a>

## Plugin configuration
While providing Zone transfers via AXFR, the Server also exposes specialized catalog zones that BIND
and other RFC9432 compliant DNS Servers use to automatically discover newly created zones and remove
deleted ones. The plugin supports views and basic DNS security via TSIG.

The plugin exposes one catalog zone per view. Each catalog zone is made available under the special
zone name **"catz"** and addtionally under **"[viewname].catz"** and may be queried through the
built-in DNS server just like any other dns zone.

For proper operation, each view requires an installed TSIG key, and the `dns-transfer-endpoint` must
be running as a separate background service using the `manage.py` command. Note that DNSSEC support
will be added once BIND9 provides a mechanism to configure it through the Catalog Zones system.

To start the transfer endpoint service in the foreground:
```
manage.py dns-transfer-endpoint --port 5354
```
This process needs to be scheduled as a background service for the built-in DNS Server to work
correctly. For Linux users with Systemd (Ubuntu, etc), Matt Kollross provides a startup unit and
instructions [here](docs/install-systemd-service.md).

### Service parameters
Parameter | Description
--------- | -------------------------------------------------------------------
--port    | Port to listen on for requests (defaults to 5354)
--address | IP of interface to bind to (defaults to 0.0.0.0)

### Plugin settings
Plugin settings should be configured under `PLUGINS_CONFIG` in `netbox_dns_bridge`:
```
PLUGINS_CONFIG = {
    'netbox_dns_bridge': {
        ...
        ...
    }
}
```

#### TSIG Authentication
Following sets the TSIG key that allows clients to query the transfer endpoint and also they key to
be used to sign NOTIFY messages to clients on zone changes. Each view should have its own unique
key to allow the plugin to identify the view the client is trying to access. Re-using the key for
multiple views yields unpredicted behavior.
```
'tsig_keys': {
    'the-view-name-here': {
        'keyname': 'the-tsig-key-name-here',
        'algorithm': 'hmac-sha256',
        'secret': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    }
}
```

#### NOTIFY
Clients may be notified of zone changes using the NOTIFY mechanism defined in RFC 1996.
When enabled, the zone transfer endpoint keeps track of any client that successfully queried the
endpoint. Once a zone has changed, NetBox informs each client about the zone changed so that the
client can request a new zone transfer.

Note that this feature uses NetBox's background job system to schedule the messages asynchronously.
In order to work, you need at least one `rq-worker` service running in the background to handle
the queued jobs.

##### NOTIFY Settings
```
'notify_clients': True
```
This enables the NOTIFY system. Defaults to False

```
'notify_client_alive_threshold_hours': 24
```
This sets how long a client is considred "alive" after it last queried the transfer endpoint. 
Once the client has failed to check in for this amout of time, it is automatically removed from the
list of clients to be notified on zone changes. Default is 24 hours.
```
'notify_over_tcp': True
```
Switch to using TCP instead of UDP. Defaults to False

#### NOTIFY to a zone's own nameservers
In addition to notifying clients that queried the transfer endpoint, the plugin can send a NOTIFY
directly to a zone's own nameservers whenever that zone's SOA serial number changes. This is useful
when you want nameservers to pull updates immediately, independent of the `notify_clients` mechanism.
Only a change of the SOA serial triggers this — other zone edits that leave the serial untouched do
not.

This can be enabled per zone, globally, or both. If neither of the settings below is configured, the
feature is disabled entirely.

**Per zone (custom field).** Create a boolean custom field (e.g. `dns_bridge_notify_ns`) that applies
to `netbox_dns > zone`, then point the plugin at it:
```
'notify_ns_custom_field_name': 'dns_bridge_notify_ns'
```
A NOTIFY is then sent for any zone whose custom field is set to `True`. This lets you toggle the
behavior per zone straight from the NetBox UI, without changing the plugin config.

**Globally (all zones).**
```
'notify_ns_all_zones': True
```
When enabled, a NOTIFY is sent for every zone on serial change, regardless of the custom field.
Defaults to `False`. The two options coexist: a NOTIFY is sent if the global switch is on **or** the
zone's custom field is set.

The nameserver addresses are resolved from NetBox DNS itself by looking up active A/AAAA records
(within the zone's view) matching each nameserver's hostname. The NOTIFY messages are signed with the
same per-view TSIG key configured under `tsig_keys`, so the receiving nameservers must accept NOTIFY
signed with that key (e.g. BIND's `allow-notify { key "..."; };`).

```
'notify_ns_port': 53
```
Destination port used for these NOTIFY messages. Defaults to 53.

As with the client NOTIFY feature, this uses NetBox's background job system, so at least one
`rq-worker` service must be running.

## Plugin compatibility
This plugin extends the netbox-plugin-dns plugin. As such the versioning was changed to match the
one of netbox-plugin-dns more closely. To guarantee compatability, ensure that the major and minor
version match between both plugins. For example, when using netbox-plugin-dns `v1.5.5` install
netbox-plugin-dns-bridge `v1.5.x`.

## Installation guide
This setup provisions a BIND9 server directly with DNS data from NetBox. BIND9 can optionally run on
a separate server. If so, any reference to 127.0.0.1 in step 6 must be replaced with the IP address
of the NetBox host. TCP and UDP traffic from the BIND9 server to the NetBox host must be allowed on
port 5354 (or the port you have configured).

This guide assumes:
- NetBox has been installed under /opt/netbox
- Bind9 is installed on the same host as NetBox
- The NetBox DNS Plugin netbox-plugin-dns is installed
- The following dns views exist in NetBox DNS:
    - `public` (the default)
    - `private`

1. Preliminaries
    - Install Bind9 on the same host that netbox is on.
    - Generate a TSIG Key for the `public` and `private` dns views respectively.

2. Adding required package
    ```
    cd netbox
    echo netbox-plugin-dns-bridge >> local_requirements.txt
    . venv/bin/activate
    pip install -r local_requirements.txt
    ```

3. Updating netbox plugin configuration (configuration.py)
    Change following line from
    ```
    PLUGINS = ['netbox_dns']
    ```
    to
    ```
    PLUGINS = ['netbox_dns', 'netbox_dns_bridge']
    ```

    Configure the DNS Bridge Plugin using the PLUGINS_CONFIG dictionary.
    Change
    ```
    PLUGINS_CONFIG = {}
    ```
    to
    ```
    PLUGINS_CONFIG = {
        "netbox_dns_bridge": {
            "tsig_keys": {
                "public": {
                    "keyname":   "public_view_key",
                    "algorithm": "hmac-sha256",
                    "secret":    "base64-encoded-secret"
                },
                "private": {
                    "keyname":   "private_view_key",
                    "algorithm": "hmac-sha256",
                    "secret":    "base64-encoded-secret"
                }
            }
        }
    }
    ```
    Note that the tsig-key attributes keyname, algorithm and secret form a
    dictionary in following python structure path:
    ```
    PLUGINS_CONFIG.netbox_dns_bridge.tsig_keys.<dns_view_name>
    ```
    This allows the plugin to map requests to the right dns view using the tsig
    signature from each request.

4. Run migrations
    ```
    manage.py migrate
    ```

5. Start listener

    This step runs the DNS endpoint used by bind to configure itself. You may want to write a
    service wrapper that runs this in the background. A guide for setting up a systemd service on
    Ubuntu is provided by Matt Kollross [here](docs/install-systemd-service.md). Dont forget to
    activate the venv if you do decide to run this service in the background.

    Note that `--port 5354` is optional. The listener will bind this port by default.
    ```
    manage.py dns-transfer-endpoint --port 5354
    ```

6. Configuring a Bind9 to interact with NetBox via the dns-transfer-endpoint endpoint. Note that its
    not possible to give all the correct details of the `options` block as it is heavily dependent
    on the Operating System used. Please dont forget to adjust as required.
   
    ```
    ########## OPTIONS ##########

    options {
        allow-update      { none; };
        allow-query       { any; };
        allow-recursion   { none; };
        notify            yes;
        min-refresh-time  60;
    };

    ########## ACLs ##########

    acl public {
        !10.0.0.0/8;
        !172.16.0.0/12;
        !192.168.0.0/16;
        any;
    };

    acl private {
        10.0.0.0/8;
        172.16.0.0/12;
        192.168.0.0/16;
    };

    ######## TSIG Keys ########
        key "public_view_key" {
            algorithm hmac-sha256;
            secret "base64-encoded-secret";
        };

        key "private_view_key" {
            algorithm hmac-sha256;
            secret "base64-encoded-secret";
        };
    ###########################


    ########## ZONES ##########
    view "public" {
        match-clients { public; };
        allow-notify { key "public_view_key"; };

        catalog-zones {
            zone "catz"
                default-masters { 127.0.0.1 port 5354 key "public_view_key"; }
                zone-directory "/var/lib/bind/zones"
                min-update-interval 1;
        };

        zone "catz" {
            type slave;
            file "/var/lib/bind/zones/catz_public";
            masters { 127.0.0.1 port 5354 key "public_view_key"; };
            notify no;
        };
    };

    view "private" {
        match-clients { private; };
        allow-notify { key "private_view_key"; };

        catalog-zones {
            zone "catz"
                default-masters { 127.0.0.1 port 5354 key "private_view_key"; }
                zone-directory "/var/lib/bind/zones"
                min-update-interval 1;
        };

        zone "catz" {
            type slave;
            file "/var/lib/bind/zones/catz_private";
            masters { 127.0.0.1 port 5354 key "private_view_key"; };
            notify no;
        };
    };
    ```

7. Restart bind - Done


