# ssh2-config
Changelog ยท Get started ยท Documentation
Developed by @veeso
Current version: 0.5.4 (27/03/2025)
--- - [ssh2-config](#ssh2-config) - [About ssh2-config](#about-ssh2-config) - [Exposed attributes](#exposed-attributes) - [Missing features](#missing-features) - [Get started ๐](#get-started-) - [Reading unsupported fields](#reading-unsupported-fields) - [How host parameters are resolved](#how-host-parameters-are-resolved) - [Resolvers examples](#resolvers-examples) - [Configuring default algorithms](#configuring-default-algorithms) - [Examples](#examples) - [Support the developer โ](#support-the-developer-) - [Contributing and issues ๐ค๐ป](#contributing-and-issues-) - [Changelog โณ](#changelog-) - [License ๐](#license-) --- ## About ssh2-config ssh2-config a library which provides a parser for the SSH configuration file, to be used in pair with the [ssh2](https://github.com/alexcrichton/ssh2-rs) crate. This library provides a method to parse the configuration file and returns the configuration parsed into a structure. The `SshConfig` structure provides all the attributes which **can** be used to configure the **ssh2 Session** and to resolve the host, port and username. Once the configuration has been parsed you can use the `query(&str)` method to query configuration for a certain host, based on the configured patterns. Even if many attributes are not exposed, since not supported, there is anyway a validation of the configuration, so invalid configuration will result in a parsing error. ### Exposed attributes - **BindAddress**: you can use this attribute to bind the socket to a certain address - **BindInterface**: you can use this attribute to bind the socket to a certain network interface - **CASignatureAlgorithms**: you can use this attribute to handle CA certificates - **CertificateFile**: you can use this attribute to parse the certificate file in case is necessary - **Ciphers**: you can use this attribute to set preferred methods with the session method `session.method_pref(MethodType::CryptCs, ...)` and `session.method_pref(MethodType::CryptSc, ...)` - **Compression**: you can use this attribute to set whether compression is enabled with `session.set_compress(value)` - **ConnectionAttempts**: you can use this attribute to cycle over connect in order to retry - **ConnectTimeout**: you can use this attribute to set the connection timeout for the socket - **HostName**: you can use this attribute to get the real name of the host to connect to - **IdentityFile**: you can use this attribute to set the keys to try when connecting to remote host. - **KexAlgorithms**: you can use this attribute to configure Key exchange methods with `session.method_pref(MethodType::Kex, algos.to_string().as_str())` - **MACs**: you can use this attribute to configure the MAC algos with `session.method_pref(MethodType::MacCs, algos..to_string().as_str())` and `session.method_pref(MethodType::MacSc, algos..to_string().as_str())` - **Port**: you can use this attribute to resolve the port to connect to - **PubkeyAuthentication**: you can use this attribute to set whether to use the pubkey authentication - **RemoteForward**: you can use this method to implement port forwarding with `session.channel_forward_listen()` - **ServerAliveInterval**: you can use this method to implement keep alive message interval - **TcpKeepAlive**: you can use this method to tell whether to send keep alive message - **UseKeychain**: (macos only) used to tell whether to use keychain to decrypt ssh keys - **User**: you can use this method to resolve the user to use to log in as ### Missing features - [Match patterns](http://man.openbsd.org/OpenBSD-current/man5/ssh_config.5#Match) (Host patterns are supported!!!) - [Tokens](http://man.openbsd.org/OpenBSD-current/man5/ssh_config.5#TOKENS) --- ## Get started ๐ First of all, add ssh2-config to your dependencies ```toml [dependencies] ssh2-config = "^0.5" ``` then parse the configuration ```rust use ssh2_config::{ParseRule, SshConfig}; use std::fs::File; use std::io::BufReader; let mut reader = BufReader::new(File::open(config_path).expect("Could not open configuration file")); let config = SshConfig::default().parse(&mut reader, ParseRule::STRICT).expect("Failed to parse configuration"); // Query attributes for a certain host let params = config.query("192.168.1.2"); ``` then you can use the parsed parameters to configure the session: ```rust use ssh2::Session; use ssh2_config::{HostParams}; fn configure_session(session: &mut Session, params: &HostParams) { if let Some(compress) = params.compression { session.set_compress(compress); } if params.tcp_keep_alive.unwrap_or(false) && params.server_alive_interval.is_some() { let interval = params.server_alive_interval.unwrap().as_secs() as u32; session.set_keepalive(true, interval); } // KEX if let Err(err) = session.method_pref( MethodType::Kex, params.kex_algorithms.algorithms().join(",").as_str(), ) { panic!("Could not set KEX algorithms: {}", err); } // host key if let Err(err) = session.method_pref( MethodType::HostKey, params.host_key_algorithms.algorithms().join(",").as_str(), ) { panic!("Could not set host key algorithms: {}", err); } // ciphers if let Err(err) = session.method_pref( MethodType::CryptCs, params.ciphers.algorithms().join(",").as_str(), ) { panic!("Could not set crypt algorithms (client-server): {}", err); } if let Err(err) = session.method_pref( MethodType::CryptSc, params.ciphers.algorithms().join(",").as_str(), ) { panic!("Could not set crypt algorithms (server-client): {}", err); } // mac if let Err(err) = session.method_pref( MethodType::MacCs, params.mac.algorithms().join(",").as_str(), ) { panic!("Could not set MAC algorithms (client-server): {}", err); } if let Err(err) = session.method_pref( MethodType::MacSc, params.mac.algorithms().join(",").as_str(), ) { panic!("Could not set MAC algorithms (server-client): {}", err); } } fn auth_with_rsakey( session: &mut Session, params: &HostParams, username: &str, password: Option<&str> ) { for identity_file in params.identity_file.unwrap_or_default().iter() { if let Ok(_) = session.userauth_pubkey_file(username, None, identity_file, password) { break; } } } ``` ### Reading unsupported fields As outlined above, ssh2-config does not support all parameters available in the man page of the SSH configuration file. If you require these fields you may still access them through the `unsupported_fields` field on the `HostParams` structure like this: ```rust use ssh2_config::{ParseRule, SshConfig}; use std::fs::File; use std::io::BufReader; let mut reader = BufReader::new(File::open(config_path).expect("Could not open configuration file")); let config = SshConfig::default().parse(&mut reader, ParseRule::ALLOW_UNSUPPORTED_FIELDS).expect("Failed to parse configuration"); // Query attributes for a certain host let params = config.query("192.168.1.2"); let forwards = params.unsupported_fields.get("dynamicforward"); ``` --- ## How host parameters are resolved This topic has been debated a lot over the years, so finally since 0.5 this has been fixed to follow the official ssh configuration file rules, as described in the MAN