Skip to content

Commit a4d5746

Browse files
authored
Generate ssh_config file with a netlab report (ipspace#2593)
The 'ssh_config' report generates a configuration file that can be included in client ~/.ssh/config file to access netlab devices straight through a client SSH session using RemoteCommand on netlab server to connect to the devices. The report also adds host names that can be used for direct SSH proxy access (for example, to run SCP) and local port forwarding based on 'netlab_ssh_forward' node variable.
1 parent 464edf9 commit a4d5746

File tree

2 files changed

+96
-11
lines changed

2 files changed

+96
-11
lines changed

docs/example/external.md

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ _netlab_ contains several mechanisms that allow you to manage physical labs, add
1515

1616
*libvirt* and *containerlab* try to add IPv4 default routes to lab devices. *libvirt* uses a DHCP option, *containerlab* installs a default route into the container network namespace[^DR_EOS]. Most network devices running in a virtual lab are thus able to reach external destinations.
1717

18-
Most box-building recipes for *libvirt* Vagrant boxes recommend using a management VRF for the management interface. The default route is thus installed into the management VRF, and the client you're using on the network device has to be VRF-aware to reach external destinations. For example, you'll have to use a command similar to **ping vrf _name_ _destination_** to ping external IP addresses.
18+
Most box-building recipes for *libvirt* Vagrant boxes recommend using a management VRF for the management interface. The default route is thus installed into the management VRF, and the client you're using on the network device must be VRF-aware to reach external destinations. For example, you'll have to use a command similar to **ping vrf _name_ _destination_** to ping external IP addresses.
1919

2020
[^DR_EOS]: The default route added to the Linux kernel by *containerlab* might not be displayed by the network operating system. For example, if you execute **show ip route** on an Arista EOS container, you won't see a default route, but you'll still be able to reach external destinations.
2121

@@ -28,7 +28,7 @@ Alternatively, use *[graphite](../extool/graphite.md)* for GUI-based SSH access
2828

2929
### Finding the Management IP Addresses
3030

31-
**netlab report mgmt** command displays the management IP addresses[^VBS] of the lab devices, protocol used to configure the devices (SSH, NETCONF or docker), and the username/password used by _netlab_ to configure the device.
31+
The **netlab report mgmt** command displays the management IP addresses of the lab devices, protocol used to configure the devices (SSH, NETCONF, or Docker), and the username/password used by _netlab_ to configure the device.
3232

3333
Alternatively, you could use Ansible inventory to find the same information:
3434

@@ -37,7 +37,34 @@ Alternatively, you could use Ansible inventory to find the same information:
3737

3838
Finally, you could display node information in YAML format with the **[netlab inspect --node _nodename_](../netlab/inspect.md)** command, or analyze the **nodes** dictionary in the `netlab.snapshot.yml` file with `yq` or a custom script.
3939

40-
[^VBS]: And SSH ports if you're using *Virtualbox*.
40+
### Using SSH Port Forwarding
41+
42+
_netlab_ can also create an SSH configuration file that you can add to your `.ssh` directory to access lab devices directly through SSH sessions using the _netlab_ host as a proxy host[^SSHDIY].
43+
44+
After starting the lab, run **netlab report ssh_config** ([more details](netlab-report)) in the lab directory and save the contents into a file in your workstation's `.ssh` directory. Use `Include` directive in the SSH `config` file[^SBF] to give your **ssh** client access to the definitions of lab devices.
45+
46+
[^SSHDIY]: If you're not familiar with SSH configuration files, explore LocalForward, ProxyJump, ProxyCommand, and RemoteCommand OpenSSH [configuration parameters](https://man.openbsd.org/ssh_config).
47+
48+
[^SBF]: At the beginning of the file
49+
50+
You might have to set several [default](topo-defaults) parameters, either in the [user default file](defaults-user-file) or by [using environment variables](defaults-env), to adapt the contents of the SSH configuration to your environment:
51+
52+
* **defaults.ssh.hostname** -- The name under which the _netlab_ server is known on your workstation (default: `netlab`). You have to set this parameter to a hostname that is resolvable on your workstation or combine it with the **defaults.ssh.publicip** parameter, in which case the SSH configuration file will include the definition of the hostname specified in this parameter[^SCTIO].
53+
* **defaults.ssh.publicip** -- The public IP address you can use to reach the _netlab_ server. Use this parameter if you're running the _netlab_ host in an environment where its public IP address might change (for example, in a public cloud).
54+
* **defaults.ssh.netlabpath** -- The `netlab` command path when it's not in the default PATH[^SPLS].
55+
56+
[^SCTIO]: Sounds confusing? Try it out; you cannot do any damage until you save the report results in a file.
57+
58+
[^SPLS]: The SSH process doing proxying on the _netlab_ server is started without executing the shell login script
59+
60+
The **ssh_config** report can also set up SSH port forwarding using the **netlab_ssh_forward** node variable. For example, using the following lab topology, you'd get access to the firewall's HTTPS port (port 443) through the workstation (`localhost`) port 8080 *after establishing an SSH session to the netlab host*.
61+
62+
```
63+
nodes:
64+
fw:
65+
netlab_ssh_forward:
66+
- 8080:443
67+
```
4168

4269
(external-connectivity-control-plane)=
4370
## Control-Plane Connectivity
@@ -46,19 +73,17 @@ If you need control-plane connectivity to your lab devices (for example, you'd l
4673

4774
To connect *libvirt* virtual machines or *containerlab* containers to the outside world, set [**libvirt.uplink**](libvirt-network-external) or [**clab.uplink**](clab-network-external) link attribute on any link in your topology.
4875

49-
*VirtualBox* uses a different connectivity model. It maps device TCP/UDP ports into host TCP/UDP ports. The default ports mapped for each network device are **ssh**, **http** and **netconf**. It's possible to add additional forwarded ports to the **defaults.providers.virtualbox.forwarded** parameter; the details are beyond the scope of this tutorial.
50-
51-
*VirtualBox* can connect VMs to the external world. That capability is not part of _netlab_ functionality; please feel free to [submit a Pull Request](../dev/guidelines.md) implementing it.
76+
*VirtualBox* uses a different connectivity model. It maps device TCP/UDP ports into host TCP/UDP ports. The default ports mapped for each network device are **ssh**, **http**, and **netconf**. You can add further forwarded ports to the **defaults.providers.virtualbox.forwarded** parameter; the details are beyond the scope of this tutorial.
5277

5378
(external-unprovisioned-devices)=
5479
## Unprovisioned Devices
5580

5681
The easiest way to add network management software (or any third-party workload) to your lab is to deploy it as a node in your network:
5782

5883
* Define an extra **linux** node in your lab topology
59-
* Use **image** node attribute to specify a Vagrant box or container image to use.
84+
* Use the **image** node attribute to specify the node's Vagrant box or container image.
6085

61-
The lab provisioning process will configure the static routes on your VM/container to allow it to reach all other devices in your lab.
86+
The lab provisioning process will configure the static routes on your VM/container so that it can reach all other devices in your lab.
6287

6388
The VM device provisioning process will fail if your VM does not contain Python (used by Ansible) or the necessary Linux CLI commands (example: **ip** to add static routes); container interface addresses and routing tables are [configured from the Linux server](clab-linux).
6489

@@ -89,7 +114,7 @@ As they are still connected to the management network, they can always reach the
89114
(external-unmanaged)=
90115
## Unmanaged Devices
91116

92-
In advanced scenarios connecting your virtual lab with the outside world, you might want to include external devices into your lab topology without managing or provisioning them[^UDC].
117+
In advanced scenarios connecting your virtual lab with the outside world, you might want to add external devices to your lab topology without managing or provisioning them[^UDC].
93118

94119
[^UDC]: Assuming you connected one or more Linux bridges in your lab with the outside world.
95120

@@ -128,8 +153,8 @@ You still have to specify the device type (either in the node or as the [default
128153

129154
If you want to create configurations for a prewired physical lab, use the [**external** provider](../labs/external.md).
130155

131-
Before using _netlab_ with a physical lab, you'll have to create a lab topology that specifies the specify management IP addresses and interface names for all devices in your lab. Once that's done, save the topology as a blueprint for further lab work.
156+
Before using _netlab_ with a physical lab, you must create a lab topology specifying the management IP addresses and interface names for all devices in your lab. Once that's done, save the topology as a blueprint for further lab work.
132157

133-
Starting with the physical lab blueprint topology, add addressing plans (if needed), configuration modules, and configuration module parameters. Use **netlab up** to start the data transformation process and configuration deployment on physical devices.
158+
Starting with the physical lab blueprint topology, add addressing plans (if needed), configuration modules, and configuration module parameters. Use **netlab up** to start the data transformation and configuration deployment on physical devices.
134159

135160
Please note that _netlab_ does not contain a cleanup procedure for physical devices -- you'll have to remove the device configurations before starting the next lab.

netsim/reports/ssh_config.j2

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{% set ssh_defaults = defaults.ssh|default({}) %}
2+
{% set hostname = ssh_defaults.hostname|default('netlab') %}
3+
{% set public_ip = ssh_defaults.publicip|default('') %}
4+
{% set netlab_path = ssh_defaults.netlabpath|default('netlab') %}
5+
{% set ssh_conn = ['paramiko','netconf','paramiko_ssh','network_cli'] %}
6+
#
7+
# This SSH configuration file allows you to connect to netlab devices running
8+
# on a remote server straight from your workstation
9+
#
10+
# Save it into the ~/.ssh directory (or similar) and include it in your ~/.ssh/config
11+
# file with the "Include" directive (which has to be before the first Host directive)
12+
#
13+
# You can change the SSH parameters with these environment variables
14+
#
15+
# NETLAB_SSH_HOSTNAME The desired hostname of the netlab server
16+
# NETLAB_SSH_PUBLICIP The IP address of the netlab server when the hostname is not resolvable
17+
# NETLAB_SSH_NETLABPATH The path to 'netlab' command (if it's not in PATH)
18+
#
19+
# Use the 'netlab_ssh_forward' node parameter to set up port forwarding, for example, to map the 'fw'
20+
# HTTPS (port 443) server into local port 8080, use the following setup:
21+
#
22+
# nodes:
23+
# fw:
24+
# netlab_ssh_forward:
25+
# - 8080:443
26+
#
27+
Host {{ hostname }}
28+
StrictHostKeyChecking off
29+
UserKnownHostsFile /dev/null
30+
{% if public_ip %}
31+
HostName {{ public_ip }}
32+
{% endif %}
33+
{% for n_name,n_data in nodes.items() if 'netlab_ssh_forward' in n_data %}
34+
{% for p_fwd in n_data.netlab_ssh_forward %}
35+
{% set p_data = p_fwd.split(':') %}
36+
LocalForward {{ p_data[0] }} {{ n_data.ansible_host }}:{{ p_data[1] }}
37+
{% endfor %}
38+
{% endfor %}
39+
40+
{% for n_name,n_data in nodes.items() %}
41+
Host {{ n_name }}
42+
HostName {{ public_ip or hostname }}
43+
RequestTTY yes
44+
RemoteCommand {{ netlab_path }} connect -i {{ defaults.multilab.id|default('default') }} {{ n_name }}
45+
UserKnownHostsFile /dev/null
46+
StrictHostKeyChecking off
47+
UserKnownHostsFile /dev/null
48+
LogLevel QUIET
49+
50+
{% endfor %}
51+
{% for n_name,n_data in nodes.items()
52+
if n_data.ansible_connection in ssh_conn %}
53+
Host {{ n_name }}.ssh
54+
HostName {{ n_data.ansible_host }}
55+
User {{ n_data.ansible_user }}
56+
ProxyJump {{ hostname }}
57+
StrictHostKeyChecking off
58+
UserKnownHostsFile /dev/null
59+
60+
{% endfor %}

0 commit comments

Comments
 (0)