Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #9816: VPN tunnel support #14276

Merged
merged 27 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
60fc28e
WIP
jeremystretch Nov 7, 2023
4880111
WIP
jeremystretch Nov 8, 2023
130288d
Add phase2_sa_lifetime_data field on IPSecProfile
jeremystretch Nov 14, 2023
255764c
Fleshed out IKE parameter choices
jeremystretch Nov 15, 2023
a4e8070
Add forms for creating tunnel terminations
jeremystretch Nov 15, 2023
bf4bc23
Add columns to TunnelTerminationTable
jeremystretch Nov 15, 2023
a616f5f
Register GraphQL schema for vpn app
jeremystretch Nov 15, 2023
c7e3362
Add tunnel column on interface tables
jeremystretch Nov 15, 2023
599d733
Tweak ordering; add unique constraint
jeremystretch Nov 15, 2023
eba9677
Workflow improvements
jeremystretch Nov 15, 2023
6d55f54
Refactor crypto models (WIP)
jeremystretch Nov 20, 2023
c1ce3c9
Add migrations
jeremystretch Nov 21, 2023
ff1bbf6
Cleanup
jeremystretch Nov 21, 2023
f600f90
Add REST API tests
jeremystretch Nov 21, 2023
c814e76
Add UI view tests
jeremystretch Nov 21, 2023
e965c6c
Add filterset tests
jeremystretch Nov 21, 2023
624fcbf
Flesh out object templates
jeremystretch Nov 22, 2023
c929fa3
Drop certificate field from IKEPolicy
jeremystretch Nov 22, 2023
667bebd
Add feature & model docs
jeremystretch Nov 22, 2023
3cf53ce
Include peer terminations on TunnelTermination view
jeremystretch Nov 22, 2023
e6c9e13
Workaround for test failure
jeremystretch Nov 22, 2023
dbed518
Review feedback
jeremystretch Nov 27, 2023
dda4071
Rename interface to termination on CableTermination
jeremystretch Nov 27, 2023
21f1de4
Implement interface filters for TunnelTermination
jeremystretch Nov 27, 2023
fd432e0
Add search indexers
jeremystretch Nov 27, 2023
9038ed8
Misc cleanup
jeremystretch Nov 27, 2023
2a64558
Add termination_type filter
jeremystretch Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/features/vpn-tunnels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Tunnels

NetBox can model private tunnels formed among virtual termination points across your network. Typical tunnel implementations include GRE, IP-in-IP, and IPSec. A tunnel may be terminated to two or more device or virtual machine interfaces.

```mermaid
flowchart TD
Termination1[TunnelTermination]
Termination2[TunnelTermination]
Interface1[Interface]
Interface2[Interface]
Tunnel --> Termination1 & Termination2
Termination1 --> Interface1
Termination2 --> Interface2
Interface1 --> Device
Interface2 --> VirtualMachine

click Tunnel "../../models/vpn/tunnel/"
click TunnelTermination1 "../../models/vpn/tunneltermination/"
click TunnelTermination2 "../../models/vpn/tunneltermination/"
```

# IPSec & IKE

NetBox includes robust support for modeling IPSec & IKE policies. These are used to define encryption and authentication parameters for IPSec tunnels.

```mermaid
flowchart TD
subgraph IKEProposals[Proposals]
IKEProposal1[IKEProposal]
IKEProposal2[IKEProposal]
end
subgraph IPSecProposals[Proposals]
IPSecProposal1[IPSecProposal]
IPSecProposal2[IPSecProposal]
end
IKEProposals --> IKEPolicy
IPSecProposals --> IPSecPolicy
IKEPolicy & IPSecPolicy--> IPSecProfile
IPSecProfile --> Tunnel

click IKEProposal1 "../../models/vpn/ikeproposal/"
click IKEProposal2 "../../models/vpn/ikeproposal/"
click IKEPolicy "../../models/vpn/ikepolicy/"
click IPSecProposal1 "../../models/vpn/ipsecproposal/"
click IPSecProposal2 "../../models/vpn/ipsecproposal/"
click IPSecPolicy "../../models/vpn/ipsecpolicy/"
click IPSecProfile "../../models/vpn/ipsecprofile/"
click Tunnel "../../models/vpn/tunnel/"
```
25 changes: 25 additions & 0 deletions docs/models/vpn/ikepolicy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# IKE Policies

An [Internet Key Exhcnage (IKE)](https://en.wikipedia.org/wiki/Internet_Key_Exchange) policy defines an IKE version, mode, and set of [proposals](./ikeproposal.md) to be used in IKE negotiation. These policies are referenced by [IPSec profiles](./ipsecprofile.md).

## Fields

### Name

The unique user-assigned name for the policy.

### Version

The IKE version employed (v1 or v2).

### Mode

The IKE mode employed (main or aggressive).

### Proposals

One or more [IKE proposals](./ikeproposal.md) supported for use by this policy.

### Pre-shared Key

A pre-shared secret key associated with this policy (optional).
39 changes: 39 additions & 0 deletions docs/models/vpn/ikeproposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# IKE Proposals

An [Internet Key Exhcnage (IKE)](https://en.wikipedia.org/wiki/Internet_Key_Exchange) proposal defines a set of parameters used to establish a secure bidirectional connection across an untrusted medium, such as the Internet. IKE proposals defined in NetBox can be referenced by [IKE policies](./ikepolicy.md), which are in turn employed by [IPSec profiles](./ipsecprofile.md).

!!! note
Some platforms refer to IKE proposals as [ISAKMP](https://en.wikipedia.org/wiki/Internet_Security_Association_and_Key_Management_Protocol), which is a framework for authentication and key exchange which employs IKE.

## Fields

### Name

The unique user-assigned name for the proposal.

### Authentication Method

The strategy employed for authenticating the IKE peer. Available options are listed below.

| Name |
|----------------|
| Pre-shared key |
| Certificate |
| RSA signature |
| DSA signature |

### Encryption Algorithm

The protocol employed for data encryption. Options include DES, 3DES, and various flavors of AES.

### Authentication Algorithm

The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations.

### Group

The [Diffie-Hellman group](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange) supported by the proposal. Group IDs are [managed by IANA](https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-8).

### SA Lifetime

The maximum lifetime for the IKE security association (SA), in seconds.
17 changes: 17 additions & 0 deletions docs/models/vpn/ipsecpolicy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# IPSec Policy

An [IPSec](https://en.wikipedia.org/wiki/IPsec) policy defines a set of [proposals](./ikeproposal.md) to be used in the formation of IPSec tunnels. A perfect forward secrecy (PFS) group may optionally also be defined. These policies are referenced by [IPSec profiles](./ipsecprofile.md).

## Fields

### Name

The unique user-assigned name for the policy.

### Proposals

One or more [IPSec proposals](./ipsecproposal.md) supported for use by this policy.

### PFS Group

The [perfect forward secrecy (PFS)](https://en.wikipedia.org/wiki/Forward_secrecy) group supported by this policy (optional).
21 changes: 21 additions & 0 deletions docs/models/vpn/ipsecprofile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# IPSec Profile

An [IPSec](https://en.wikipedia.org/wiki/IPsec) profile defines an [IKE policy](./ikepolicy.md), [IPSec policy](./ipsecpolicy.md), and IPSec mode used for establishing an IPSec tunnel.

## Fields

### Name

The unique user-assigned name for the profile.

### Mode

The IPSec mode employed by the profile: Encapsulating Security Payload (ESP) or Authentication Header (AH).

### IKE Policy

The [IKE policy](./ikepolicy.md) associated with the profile.

### IPSec Policy

The [IPSec policy](./ipsecpolicy.md) associated with the profile.
25 changes: 25 additions & 0 deletions docs/models/vpn/ipsecproposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# IPSec Proposal

An [IPSec](https://en.wikipedia.org/wiki/IPsec) proposal defines a set of parameters used in negotiating security associations for IPSec tunnels. IPSec proposals defined in NetBox can be referenced by [IPSec policies](./ipsecpolicy.md), which are in turn employed by [IPSec profiles](./ipsecprofile.md).

## Fields

### Name

The unique user-assigned name for the proposal.

### Encryption Algorithm

The protocol employed for data encryption. Options include DES, 3DES, and various flavors of AES.

### Authentication Algorithm

The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations.

### SA Lifetime (Seconds)

The maximum amount of time for which the security association (SA) may be active, in seconds.

### SA Lifetime (Data)

The maximum amount of data which can be transferred within the security association (SA) before it must be rebuilt, in kilobytes.
36 changes: 36 additions & 0 deletions docs/models/vpn/tunnel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Tunnels

A tunnel represents a private virtual connection established among two or more endpoints across a shared infrastructure by employing protocol encapsulation. Common encapsulation techniques include [Generic Routing Encapsulation (GRE)](https://en.wikipedia.org/wiki/Generic_Routing_Encapsulation), [IP-in-IP](https://en.wikipedia.org/wiki/IP_in_IP), and [IPSec](https://en.wikipedia.org/wiki/IPsec). NetBox supports modeling both peer-to-peer and hub-and-spoke tunnel topologies.

Device and virtual machine interfaces are associated to tunnels by creating [tunnel terminations](./tunneltermination.md).

## Fields

### Name

A unique name assigned to the tunnel for identification.

### Status

The operational status of the tunnel. By default, the following statuses are available:

| Name |
|----------------|
| Planned |
| Active |
| Disabled |

!!! tip "Custom tunnel statuses"
Additional tunnel statuses may be defined by setting `Tunnel.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.

### Encapsulation

The encapsulation protocol or technique employed to effect the tunnel. NetBox supports GRE, IP-in-IP, and IPSec encapsulations.

### Tunnel ID

An optional numeric identifier for the tunnel.

### IPSec Profile

For IPSec tunnels, this is the [IPSec Profile](./ipsecprofile.md) employed to negotiate security associations.
30 changes: 30 additions & 0 deletions docs/models/vpn/tunneltermination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Tunnel Terminations

A tunnel termination connects a device or virtual machine interface to a [tunnel](./tunnel.md). The tunnel must be created before any terminations may be added.

## Fields

### Tunnel

The [tunnel](./tunnel.md) to which this termination is made.

### Role

The functional role of the attached interface. The following options are available:

| Name | Description |
|-------|--------------------------------------------------|
| Peer | An endpoint in a point-to-point or mesh topology |
| Hub | A central point in a hub-and-spoke topology |
| Spoke | An edge point in a hub-and-spoke topology |

!!! note
Multiple hub terminations may be attached to a tunnel.

### Termination

The device or virtual machine interface terminated to the tunnel.

### Outside IP

The public or underlay IP address with which this termination is associated. This is the IP to which peers will route tunneled traffic.
9 changes: 9 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ nav:
- Circuits: 'features/circuits.md'
- Wireless: 'features/wireless.md'
- Virtualization: 'features/virtualization.md'
- VPN Tunnels: 'features/vpn-tunnels.md'
- Tenancy: 'features/tenancy.md'
- Contacts: 'features/contacts.md'
- Search: 'features/search.md'
Expand Down Expand Up @@ -252,6 +253,14 @@ nav:
- ClusterType: 'models/virtualization/clustertype.md'
- VMInterface: 'models/virtualization/vminterface.md'
- VirtualMachine: 'models/virtualization/virtualmachine.md'
- VPN:
jeremystretch marked this conversation as resolved.
Show resolved Hide resolved
- IKEPolicy: 'models/vpn/ikepolicy.md'
- IKEProposal: 'models/vpn/ikeproposal.md'
- IPSecPolicy: 'models/vpn/ipsecpolicy.md'
- IPSecProfile: 'models/vpn/ipsecprofile.md'
- IPSecProposal: 'models/vpn/ipsecproposal.md'
- Tunnel: 'models/vpn/tunnel.md'
- TunnelTermination: 'models/vpn/tunneltermination.md'
- Wireless:
- WirelessLAN: 'models/wireless/wirelesslan.md'
- WirelessLANGroup: 'models/wireless/wirelesslangroup.md'
Expand Down
2 changes: 1 addition & 1 deletion netbox/core/management/commands/nbshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand

APPS = ('circuits', 'core', 'dcim', 'extras', 'ipam', 'tenancy', 'users', 'virtualization', 'wireless')
APPS = ('circuits', 'core', 'dcim', 'extras', 'ipam', 'tenancy', 'users', 'virtualization', 'vpn', 'wireless')

BANNER_TEXT = """### NetBox interactive shell ({node})
### Python {python} | Django {django} | NetBox {netbox}
Expand Down
10 changes: 10 additions & 0 deletions netbox/dcim/models/device_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,10 @@ def save(self, *args, **kwargs):

return super().save(*args, **kwargs)

@property
def tunnel_termination(self):
return self.tunnel_terminations.first()

@property
def count_ipaddresses(self):
return self.ip_addresses.count()
Expand Down Expand Up @@ -720,6 +724,12 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
object_id_field='interface_id',
related_query_name='+'
)
tunnel_terminations = GenericRelation(
to='vpn.TunnelTermination',
content_type_field='termination_type',
object_id_field='termination_id',
related_query_name='interface'
)
l2vpn_terminations = GenericRelation(
to='ipam.L2VPNTermination',
content_type_field='assigned_object_type',
Expand Down
13 changes: 10 additions & 3 deletions netbox/dcim/tables/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,12 @@ class BaseInterfaceTable(NetBoxTable):
orderable=False,
verbose_name=_('L2VPN')
)
tunnel = tables.Column(
accessor=tables.A('tunnel_termination__tunnel'),
linkify=True,
orderable=False,
verbose_name=_('Tunnel')
)
untagged_vlan = tables.Column(
verbose_name=_('Untagged VLAN'),
linkify=True
Expand Down Expand Up @@ -646,7 +652,8 @@ class Meta(DeviceComponentTable.Meta):
'speed', 'speed_formatted', 'duplex', 'mode', 'mac_address', 'wwn', 'poe_mode', 'poe_type', 'rf_role', 'rf_channel',
'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable',
'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn',
'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'inventory_items', 'created', 'last_updated',
'tunnel', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'inventory_items', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')

Expand Down Expand Up @@ -682,8 +689,8 @@ class Meta(DeviceComponentTable.Meta):
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'enabled', 'type', 'parent', 'bridge', 'lag',
'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency',
'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link',
'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'ip_addresses', 'fhrp_groups',
'untagged_vlan', 'tagged_vlans', 'actions',
'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses',
'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mtu', 'mode', 'description', 'ip_addresses',
Expand Down
10 changes: 10 additions & 0 deletions netbox/dcim/tables/template_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@
<i class="mdi mdi-wifi-off" aria-hidden="true"></i>
</a>
{% endif %}
{% elif record.type == 'virtual' %}
{% if perms.vpn.add_tunnel and not record.tunnel_termination %}
<a href="{% url 'vpn:tunnel_add' %}?termination1_type=dcim.device&termination1_parent={{ record.device.pk }}&termination1_interface={{ record.pk }}&return_url={% url 'dcim:device_interfaces' pk=object.pk %}" title="Create a tunnel" class="btn btn-success btn-sm">
<i class="mdi mdi-tunnel-outline" aria-hidden="true"></i>
</a>
{% elif perms.vpn.delete_tunneltermination and record.tunnel_termination %}
<a href="{% url 'vpn:tunneltermination_delete' pk=record.tunnel_termination.pk %}?return_url={% url 'dcim:device_interfaces' pk=object.pk %}" title="Remove tunnel" class="btn btn-danger btn-sm">
<i class="mdi mdi-tunnel-outline" aria-hidden="true"></i>
</a>
{% endif %}
{% elif record.is_wired and perms.dcim.add_cable %}
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
<a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
Expand Down
1 change: 1 addition & 0 deletions netbox/netbox/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def get(self, request, format=None):
'tenancy': reverse('tenancy-api:api-root', request=request, format=format),
'users': reverse('users-api:api-root', request=request, format=format),
'virtualization': reverse('virtualization-api:api-root', request=request, format=format),
'vpn': reverse('vpn-api:api-root', request=request, format=format),
'wireless': reverse('wireless-api:api-root', request=request, format=format),
})

Expand Down
2 changes: 2 additions & 0 deletions netbox/netbox/graphql/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from tenancy.graphql.schema import TenancyQuery
from users.graphql.schema import UsersQuery
from virtualization.graphql.schema import VirtualizationQuery
from vpn.graphql.schema import VPNQuery
from wireless.graphql.schema import WirelessQuery


Expand All @@ -21,6 +22,7 @@ class Query(
IPAMQuery,
TenancyQuery,
VirtualizationQuery,
VPNQuery,
WirelessQuery,
*registry['plugins']['graphql_schemas'], # Append plugin schemas
graphene.ObjectType
Expand Down
Loading