From e2866443de22d3d4571e8e04bddbe890a7dc9c24 Mon Sep 17 00:00:00 2001 From: danielrConfig Date: Mon, 31 Aug 2026 09:08:22 +0100 Subject: [PATCH] Add Juniper JUNOS SSH template with KEX algorithm override, and validator/docs support for the new connect.kexOverride/kexAlgorithms keys. Includes CHANGELOG entry; no template renames or path changes. --- CHANGELOG.md | 3 ++ docs/ORDER-OF-OPERATIONS.md | 2 +- docs/TEMPLATES.md | 2 ++ juniper/juniper-junos-ssh-noenable-kex.yml | 37 ++++++++++++++++++++++ scripts/validate_templates.py | 3 +- 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 juniper/juniper-junos-ssh-noenable-kex.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 65a4d47..0ae6491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ A major version here means paths changed. Every rename and deletion is mapped in disable paging with `terminal length 0` rather than the EXOS `disable clipaging`. - `extreme/README.md`, explaining which of the two Extreme templates to use and how to tell the families apart. +- `juniper/juniper-junos-ssh-noenable-kex.yml`, adding the new `kexOverride` / + `kexAlgorithms` connect keys to force a legacy KEX algorithm list for JunOS devices + that don't negotiate cleanly against phpseclib's modern defaults. ## [2.0.0] - 2026-08-16 diff --git a/docs/ORDER-OF-OPERATIONS.md b/docs/ORDER-OF-OPERATIONS.md index dcb1a61..c17c147 100644 --- a/docs/ORDER-OF-OPERATIONS.md +++ b/docs/ORDER-OF-OPERATIONS.md @@ -27,7 +27,7 @@ Entry point `SSHConnectionManager::SSHConnectionAndOutput()`, `SSH/SSHConnection | --- | --- | --- | --- | | 1 | Build the parameters object from the template and device record | all sections | `SSH/Connect.php:81-152` | | 2 | Port sanity check | `connect.port` | `SSH/Connect.php:156,170-177` | -| 3 | Open the SSH socket | `connect.port`, `connect.timeout` | `SSH/Connect.php:157` | +| 3 | Open the SSH socket, then restrict the KEX algorithm list if the template opts in | `connect.port`, `connect.timeout`, `connect.kexOverride`, `connect.kexAlgorithms` | `SSH/Connect.php:164-165,181-188` | | 4 | Apply the terminal window size | `options.setWindowSize` | `SSH/Connect.php:158-160` | | 5 | Stash the ANSI terminal dimensions for later | `options.setTerminalDimensions` | `SSH/Connect.php:161-163` | | 6 | Escape `~` in every value that will be used as a regex | `config.pagingCmd`, `auth.enableCmd`, `auth.enablePassPrmpt`, device prompt | `SSH/Login.php:281-287` | diff --git a/docs/TEMPLATES.md b/docs/TEMPLATES.md index a2e97e7..f0ad7f7 100644 --- a/docs/TEMPLATES.md +++ b/docs/TEMPLATES.md @@ -155,6 +155,8 @@ Script templates never build a connection object, so neither key is read for `pr | `fallbackProtocol` | string | `ssh`, `telnet` | Optional, default none | dispatcher | **Pro only** | Undocumented before this legend. Set it to the other protocol and rConfig resolves which one the device actually answers on, caches the result, then dispatches normally. Only activates when it differs from `protocol` and both are ssh or telnet. `ProtocolFallbackConnectionManager.php:28,50-55,64` | | `fallbackPort` | int | 1 to 65535 | Optional, defaults to 22 for ssh or 23 for telnet | dispatcher | **Pro only** | Undocumented before this legend. Port used for the fallback attempt. A device port override still wins. `ProtocolFallbackConnectionManager.php:30,70-91` | | `probeTimeout` | int | clamped to 1 to 10 | Optional, falls back to `timeout`, then `5` | dispatcher | **Pro only** | Undocumented before this legend. Seconds to wait when testing whether a port is open. Values outside 1 to 10 are clamped. `ProtocolFallbackConnectionManager.php:190-196` | +| `kexOverride` | string | tolerant on/off (`on`, `yes`, `true`, `1` and their negatives via `TemplateValues::isEnabled()`; this repo's authoring convention and validator still require the literal `on`/`off` string) | Optional, default off (no-op) | ssh | Core and Pro | No-op unless `kexAlgorithms` is also a non-empty list. `SSH/Connect.php:97,181-188`; `TemplateValues.php:23-38` | +| `kexAlgorithms` | list of strings | KEX algorithm names accepted by phpseclib3's `SSH2::setPreferredAlgorithms()` | Optional, default none | ssh | Core and Pro | Applied via `setPreferredAlgorithms(['kex' => ...])` immediately after the `SSH2` object is constructed, before the handshake. No-op if empty or `kexOverride` is off. `SSH/Connect.php:98,164-165,187` | --- diff --git a/juniper/juniper-junos-ssh-noenable-kex.yml b/juniper/juniper-junos-ssh-noenable-kex.yml new file mode 100644 index 0000000..c5a4ce6 --- /dev/null +++ b/juniper/juniper-junos-ssh-noenable-kex.yml @@ -0,0 +1,37 @@ +# rConfig connection template +## Edition: core +## Status: community-tested +## Tested-on: rConfig V6, V7 and V8 +## Docs: https://docs.rconfig.com/device-management/connection-templates/ +## Community: https://github.com/rconfig/rConfig-templates +## Note: all free-text values must be wrapped in double quotes " " + +main: + name: "Juniper JUNOS - SSH - No Enable - KEX Override" + desc: "Juniper JUNOS SSH based connection without enable mode, overriding the negotiated KEX algorithm list for devices that need a legacy key exchange" + +connect: + timeout: 60 # Connection timeout (in seconds) + protocol: ssh # Protocol: ssh + port: 22 # Port number + kexOverride: on # Force the KEX algorithm list below instead of phpseclib defaults + kexAlgorithms: # KEX algorithms offered, most preferred first + # add/remove algorithms as needed for your device - this is the minimum confirmed to work against Juniper OpenSSH_7.5 + - "diffie-hellman-group14-sha256" + +auth: + username: "login:" # Username prompt + password: "password:" # Password prompt + enable: off # Enable mode disabled + enableCmd: "configure" # Enable command (not used) + enablePassPrmpt: "password:" # Enable password prompt (not used) + hpAnyKeyStatus: off # 'Press any key' handling disabled + hpAnyKeyPrmpt: "press any key" # Custom 'press any key' prompt + +config: + linebreak: "r" # Linebreak format (set to 'r') + paging: on # CLI paging enabled + pagingCmd: "set cli screen-length 0" # Disable paging command + resetPagingCmd: "set cli screen-width 1024" # Reset paging command + saveConfig: "commit" # Save configuration command + exitCmd: "exit" # Exit command diff --git a/scripts/validate_templates.py b/scripts/validate_templates.py index 39f4911..f6d0205 100644 --- a/scripts/validate_templates.py +++ b/scripts/validate_templates.py @@ -60,6 +60,7 @@ class RConfigLoader(yaml.SafeLoader): "protocol", "port", "timeout", "isNonInteractiveMode", "idletimeout", "sshAuth", "tl1Transport", "tl1Gateway", "tl1NeighbourCmd", "fallbackProtocol", "fallbackPort", "probeTimeout", + "kexOverride", "kexAlgorithms", }, "auth": { "username", "password", "enable", "enableCmd", "enablePassPrmpt", @@ -103,7 +104,7 @@ class RConfigLoader(yaml.SafeLoader): KNOWN_PROTOCOLS = set(MANDATORY) # Keys whose value must be the string "on" or "off", never a YAML boolean. -ONOFF_KEYS = [("auth", "enable"), ("config", "paging"), ("auth", "hpAnyKeyStatus")] +ONOFF_KEYS = [("auth", "enable"), ("config", "paging"), ("auth", "hpAnyKeyStatus"), ("connect", "kexOverride")] # Header HEADER_TITLE = "# rConfig connection template"