Skip to content

Commit 2600141

Browse files
committed
support user-defined ssh private keys for hosts
1 parent a882427 commit 2600141

File tree

9 files changed

+216
-212
lines changed

9 files changed

+216
-212
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@ build:
1414
clean:
1515
@rm -rf build
1616

17+
run:
18+
@bash main.sh
19+
1720
test:
1821
@./test.sh

README.md

Lines changed: 55 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
1-
# SSH Tunnel Swarm
1+
# ssh-tunnel-swarm
22

33
![ssh-tunnel-swarm](https://raw.githubusercontent.com/psyb0t/ssh-tunnel-swarm/master/assets/ssh-tunnel-swarm.png)
44

5-
SSH Tunnel Swarm is a powerful shell script tool for managing multiple SSH tunnels concurrently. It simplifies the process of creating and managing both forward and reverse SSH tunnels by applying a predefined set of rules for each tunnel.
5+
ssh-tunnel-swarm is a powerful shell script tool for managing multiple SSH tunnels concurrently. It simplifies the process of creating and managing both forward and reverse SSH tunnels by applying a predefined set of rules for each tunnel.
66

77
The script supports the configuration of multiple SSH connections and can establish tunnels based on defined rules.
88

99
## Table of Contents
1010

11-
- [SSH Tunnel Swarm](#ssh-tunnel-swarm)
12-
- [Features](#features)
13-
- [Prerequisites](#prerequisites)
14-
- [Installation](#installation)
15-
- [Installing for the current user](#installing-for-the-current-user)
16-
- [Installing for all users](#installing-for-all-users)
17-
- [Configuration](#configuration)
18-
- [Environment Variables](#environment-variables)
19-
- [Tunnel Rules](#tunnel-rules)
20-
- [Usage](#usage)
21-
- [Logging](#logging)
11+
- [Features](#features)
12+
- [Prerequisites](#prerequisites)
13+
- [Installation](#installation)
14+
- [Installing for all users](#installing-for-all-users)
15+
- [Installing for the current user](#installing-for-the-current-user)
16+
- [Configuration](#configuration)
17+
- [Environment Variables](#environment-variables)
2218
- [Supported Log Levels](#supported-log-levels)
23-
- [Important Notes](#important-notes)
24-
- [Contributing](#contributing)
25-
- [License](#license)
26-
- [TODO](#todo)
27-
- [Glossary](#glossary)
19+
- [Tunnel Rules](#tunnel-rules)
20+
- [Example](#example)
21+
- [Usage](#usage)
22+
- [Important Notes](#important-notes)
23+
- [License](#license)
24+
- [TODO](#todo)
2825

2926
## Features
3027

@@ -45,76 +42,24 @@ This script is designed to be run in a Unix-like environment.
4542

4643
## Installation
4744

48-
To install `ssh-tunnel-swarm`, the first step is to check if `wget` is installed on your system by running `wget --version`.
45+
Execute the following command to download `ssh-tunnel-swarm`:
4946

50-
If it is installed, the output should be similar to this:
51-
52-
```
53-
GNU Wget 1.21.2 built on linux-gnu.
54-
55-
-cares +digest -gpgme +https +ipv6 +iri +large-file -metalink +nls
56-
+ntlm +opie +psl +ssl/openssl
57-
58-
Wgetrc:
59-
/etc/wgetrc (system)
60-
Locale:
61-
/usr/share/locale
62-
Compile:
63-
gcc -DHAVE_CONFIG_H -DSYSTEM_WGETRC="/etc/wgetrc"
64-
-DLOCALEDIR="/usr/share/locale" -I. -I../../src -I../lib
65-
-I../../lib -Wdate-time -D_FORTIFY_SOURCE=2 -DHAVE_LIBSSL -DNDEBUG
66-
-g -O2 -ffile-prefix-map=/build/wget-8g5eYO/wget-1.21.2=.
67-
-flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects
68-
-fstack-protector-strong -Wformat -Werror=format-security
69-
-DNO_SSLv2 -D_FILE_OFFSET_BITS=64 -g -Wall
70-
Link:
71-
gcc -DHAVE_LIBSSL -DNDEBUG -g -O2
72-
-ffile-prefix-map=/build/wget-8g5eYO/wget-1.21.2=. -flto=auto
73-
-ffat-lto-objects -flto=auto -ffat-lto-objects
74-
-fstack-protector-strong -Wformat -Werror=format-security
75-
-DNO_SSLv2 -D_FILE_OFFSET_BITS=64 -g -Wall -Wl,-Bsymbolic-functions
76-
-flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now
77-
-lpcre2-8 -luuid -lidn2 -lssl -lcrypto -lz -lpsl ftp-opie.o
78-
openssl.o http-ntlm.o ../lib/libgnu.a
79-
80-
Copyright (C) 2015 Free Software Foundation, Inc.
81-
License GPLv3+: GNU GPL version 3 or later
82-
<http://www.gnu.org/licenses/gpl.html>.
83-
This is free software: you are free to change and redistribute it.
84-
There is NO WARRANTY, to the extent permitted by law.
85-
86-
Originally written by Hrvoje Niksic <hniksic@xemacs.org>.
87-
Please send bug reports and questions to <bug-wget@gnu.org>.
47+
```shell
48+
wget -qO- https://raw.githubusercontent.com/psyb0t/ssh-tunnel-swarm/master/tools/downloader.sh | bash
8849
```
8950

90-
If `wget` is not installed, you can easily install it using the package manager for your operating system. Here are the installation commands for some known operating systems:
91-
92-
- Debian/Ubuntu-based systems: `sudo apt-get install wget`
93-
- Arch Linux-based systems: `sudo pacman -S wget`
94-
- Fedora-based systems: `sudo dnf install wget`
95-
- CentOS/RHEL-based systems: `sudo yum install wget`
96-
- openSUSE-based systems: `sudo zypper install wget`
97-
- Alpine Linux-based systems: `sudo apk add wget`
98-
- FreeBSD-based systems: `sudo pkg install wget`
99-
- NetBSD-based systems: `sudo pkgin install wget`
100-
- OpenBSD-based systems: `sudo pkg_add wget`
101-
- macOS with Homebrew installed: `brew install wget`
102-
- Tiny Core Linux: `tce-load -wi wget`
103-
104-
If your operating system is not listed above, you can visit the `wget` website at https://www.gnu.org/software/wget/ and download it from there.
51+
After the download is complete, you can use `ssh-tunnel-swarm` from the current location by executing `./ssh-tunnel-swarm` but a true installation allows you to use it from any directory.
10552

106-
Once `wget` is installed, execute the following command to download `ssh-tunnel-swarm`:
53+
### Installing for all users
10754

10855
```shell
109-
wget -qO- https://raw.githubusercontent.com/psyb0t/ssh-tunnel-swarm/master/tools/downloader.sh | bash
56+
sudo mv ssh-tunnel-swarm /usr/bin/
11057
```
11158

112-
After the download is complete, you can use `ssh-tunnel-swarm` from the current location by executing `./ssh-tunnel-swarm` but a true installation allows you to use it from any directory.
113-
11459
### Installing for the current user
11560

11661
```shell
117-
mkdir ~/bin
62+
mkdir -p ~/bin
11863
mv ssh-tunnel-swarm ~/bin/
11964
```
12065

@@ -128,7 +73,7 @@ echo $PATH | grep -q "$HOME/bin" && echo "The $HOME/bin directory is already in
12873

12974
This command will output a message indicating whether `$HOME/bin` is already in your path.
13075

131-
If it is not, execute the following command for either `bash` or `zsh`:
76+
If it is not, add it to your shell profile file:
13277

13378
For `bash`:
13479

@@ -144,12 +89,6 @@ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
14489
source ~/.zshrc
14590
```
14691

147-
## Installing for all users
148-
149-
```shell
150-
sudo mv ssh-tunnel-swarm /usr/bin/
151-
```
152-
15392
## Configuration
15493

15594
### Environment Variables
@@ -160,17 +99,29 @@ sudo mv ssh-tunnel-swarm /usr/bin/
16099

161100
- **LOG_FILE**: This determines the output destination of the log messages. If set, log messages will be written to the specified file. If not set, logs will be printed to stdout.
162101

163-
- **LOG_LEVEL**: This determines the severity level of the messages to be logged. Messages with a severity level less than this will not be logged. For example, if `LOG_LEVEL` is set to `INFO`, then `DEBUG` messages won't be logged. Default value if not set is `DEBUG`. You can find all of the [supported log levels here](#supported-log-levels).
102+
- **LOG_LEVEL**: This determines the severity level of the messages to be logged. Messages with a severity level less than this will not be logged. For example, if `LOG_LEVEL` is set to `INFO`, then `DEBUG` messages won't be logged. Default value if not set is `INFO`.
103+
104+
#### Supported Log Levels
105+
106+
The logger recognizes four levels of logging:
107+
108+
- **DEBUG**: These are verbose-level messages and are usually useful during development or debugging sessions. They provide deep insights about what's going on.
109+
110+
- **INFO**: These messages provide general feedback about the application processes and state. They are used to confirm that things are working as expected.
111+
112+
- **ERROR**: These are messages that indicate a problem that prevented a function or process from completing successfully.
113+
114+
- **FATAL**: These messages indicate a severe problem that has caused the application to stop. They require immediate attention.
164115

165116
### Tunnel Rules
166117

167-
SSH Tunnel Swarm reads the tunnel rules for each host from a file specified by the `RULES_FILE` environment variable. Each entry within the file should include the username, hostname, port, and the tunnels to establish. For instance:
118+
ssh-tunnel-swarm reads the tunnel rules for each host from a file specified by the `RULES_FILE` environment variable. Each entry within the file should include the username, hostname, port, SSH private key and the tunnels to establish. For instance:
168119

169120
```
170-
aparker@host789:34567
121+
aparker@host789:34567=/home/aparker/.ssh/id_rsa
171122
reverse host789.example.com:5432:172.16.0.5:5432
172123
173-
sjones@host012:67890
124+
sjones@host012:67890=/path/to/ssh/private/key
174125
reverse host012.example.com:3000:10.20.30.40:3000
175126
forward 172.20.0.2:6060:host012.example.com:4444
176127
reverse 10.0.0.5:5678:host789.example.com:1234
@@ -179,7 +130,9 @@ forward host789.example.com:9876:172.16.0.5:4321
179130

180131
Each block represents an SSH connection where:
181132

182-
- The first line is the username, host, and port to connect to.
133+
- The first line is the username, host, port to connect to and the private SSH key to use. The syntax is:
134+
`user@hostname:port=/path/to/private/ssh/key`
135+
183136
- The following lines are the SSH tunnels to establish for that connection, with one tunnel per line. The syntax is:
184137
`direction local-interface:local-port:remote-interface:remote-port`
185138

@@ -188,7 +141,7 @@ Each block represents an SSH connection where:
188141
**Set up a reverse tunnel from your local machine to a VPS having SSH listening on port 22**
189142

190143
```
191-
user@myvps.com:22
144+
user@myvps.com:22=/path/to/ssh/private/key
192145
reverse localhost:8080:0.0.0.0:80
193146
```
194147

@@ -197,10 +150,10 @@ Now when you access http://myvps.com/ you'll access your local service.
197150
**Set up a reverse tunnel from your local machine to 2 VPSs having SSH listening on port 22**
198151

199152
```
200-
user@myvps.com:22
153+
user@myvps.com:22=/path/to/ssh/private/key
201154
reverse localhost:8080:0.0.0.0:80
202155
203-
user@myothervps.com:22
156+
user@myothervps.com:22=/path/to/ssh/private/key
204157
reverse localhost:8080:0.0.0.0:80
205158
```
206159

@@ -209,7 +162,7 @@ Now when you access both http://myvps.com/ and http://myothervps.com/ you'll acc
209162
**Set up a forward tunnel from a remote machine to your computer**
210163

211164
```
212-
user@enterprise.com:22
165+
user@enterprise.com:22=/path/to/ssh/private/key
213166
forward localhost:6366:10.137.82.201:636
214167
```
215168

@@ -225,49 +178,19 @@ LOG_LEVEL=DEBUG \
225178
ssh-tunnel-swarm
226179
```
227180

228-
## Logging
229-
230-
SSH Tunnel Swarm includes a logging functionality that provides visibility into the operations and state of your SSH connections.
231-
232-
It is designed to enable configurable log levels and output destinations and provides different levels of logging based on the severity of the log message. This is particularly useful in complex scripts or systems where detailed logging is beneficial for development, debugging, or ongoing system maintenance.
233-
234-
### Supported Log Levels
235-
236-
The logger recognizes four levels of logging:
237-
238-
- **DEBUG**: These are verbose-level messages and are usually useful during development or debugging sessions. They provide deep insights about what's going on.
239-
240-
- **INFO**: These messages provide general feedback about the application processes and state. They are used to confirm that things are working as expected.
241-
242-
- **ERROR**: These are messages that indicate a problem that prevented a function or process from completing successfully.
243-
244-
- **FATAL**: These messages indicate a severe problem that has caused the application to stop. They require immediate attention.
245-
246181
## Important Notes
247182

248-
- SSH Tunnel Swarm does not handle SSH authentication(yet). Please ensure that the necessary SSH key is available(currently only the default one is used).
183+
- ssh-tunnel-swarm does not handle SSH password authentication.
249184

250-
- Make sure you have the required permissions on your local and remote systems to establish SSH connections and tunnels.
185+
- Always use this script responsibly make sure you have the required permissions on your local and remote systems to establish SSH connections and tunnels.
251186

252-
- All SSH connections are established with -o StrictHostKeyChecking=no for convenience. However, this option may expose you to potential security risks.
187+
- All SSH connections are established with `-o StrictHostKeyChecking=yes`.
253188

254-
- Always use this script responsibly and ensure you have the permissions to establish tunnels with your target hosts.
255-
256-
## Contributing
257-
258-
I welcome your contributions. Please submit a pull request with your improvements. Make sure to adhere to the existing coding style and ensure all tests pass before submitting your PR.
259-
260-
### Clone the repository:
261-
262-
```shell
263-
git clone https://github.com/psyb0t/ssh-tunnel-swarm.git
264-
cd ssh-tunnel-swarm
265-
make test
266-
```
189+
- With `StrictHostKeyChecking=yes`, the client will refuse to connect to servers whose host key is not known or has changed since it was last recorded. This may lead to initial connection failure if the host key is not already in the known_hosts file.
267190

268-
If all tests run you're ready do go
191+
It is your responsibility to ensure that the `known_hosts` file is up to date with the public keys of the remote hosts you wish to connect to. You can manually add a host's public key to your `known_hosts` file, or you can retrieve it using SSH on a trusted network before running ssh-tunnel-swarm.
269192

270-
To execute the script in development you can either just run `bash main.sh` or execute `make build` and run the compiled script `./build/ssh-tunnel-swarm`
193+
Note that in some cases, you might have to manually remove outdated or changed host keys from your `known_hosts` file. This situation can arise if you're connecting to a server that has had its SSH keys regenerated.
271194

272195
## License
273196

@@ -277,20 +200,6 @@ By using this software, you agree to abide by the terms of the **WTFPL**. If you
277200

278201
## TODO
279202

280-
- add support for specifying keys for each host
281-
- add more tests
282-
283-
## Glossary
284-
285-
- **SSH**: Secure Shell is a protocol used to securely connect to a remote server/system.
286-
- **Tunnel**: In the context of SSH, a tunnel is a route through which the entirety of your data is going to pass.
287-
- **Forward Tunnel (Local Port Forwarding)**: Forwarding calls for a specific IP and port from the client system to an IP and port on the server system.
288-
- **Reverse Tunnel (Remote Port Forwarding)**: Allows the server to receive a connection as a client from the client system.
289-
- **SSH Key**: A way of logging into an SSH/SFTP account using a cryptographic pair of keys, hence providing an alternative way to password-based logins.
290-
- **Bash**: A shell, or command language interpreter, for the GNU operating system.
291-
- **Shell Script**: A computer program designed to be run by the Unix shell, a command-line interpreter.
292-
- **wget**: A free utility for non-interactive download of files from the web. It supports HTTP, HTTPS, and FTP protocols and can retrieve files through HTTP proxies.
293-
- **PATH**: An environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, specifying a set of directories where executable programs are located.
294-
- **$HOME**: An environment variable that displays the path of the home directory of the current user.
295-
- **WTFPL**: Do What The Fuck You Want To Public License, a very permissive license for software and other scientific or artistic works that offers a huge degree of freedom.
296-
- **GNU**: Stands for GNU's Not Unix, an extensive collection of free software, which includes the GNU Project, the GNU Operating System, and the GNU General Public License.
203+
- refactor
204+
- better error handling
205+
- better testing utils

common_test.sh

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#!/bin/bash
22
# Function to print a failure message
33
print_failure() {
4-
local message="$1"
5-
local expected="$2"
6-
local actual="$3"
7-
local is_error_check="$4"
4+
local function_name="$1"
5+
local message="$2"
6+
local expected="$3"
7+
local actual="$4"
8+
local is_error_check="$5"
89

910
local check_type
1011
if [[ "$is_error_check" -eq 1 ]]; then
@@ -13,15 +14,16 @@ print_failure() {
1314
check_type="Equality check"
1415
fi
1516

16-
echo "FAIL - Test failed: $message. $check_type. Expected '$expected', but got '$actual'"
17+
echo "FAIL - ${function_name}: assert failed: $message. $check_type. Expected '$expected', but got '$actual'"
1718
exit 1
1819
}
1920

2021
# Function to print a success message
2122
print_success() {
22-
local message="$1"
23+
local function_name="$1"
24+
local message="$2"
2325

24-
echo "OK - Test passed: $message"
26+
echo "OK - ${function_name}: assert passed: $message"
2527
}
2628

2729
# Assert function to check if actual and expected values are the same
@@ -31,9 +33,9 @@ assert_equals() {
3133
local message="$3"
3234

3335
if [[ "$actual" == "$expected" ]]; then
34-
print_success "$message"
36+
print_success "${FUNCNAME[0]}" "$message"
3537
else
36-
print_failure "$message" "$expected" "$actual" 0
38+
print_failure "${FUNCNAME[0]}" "$message" "$expected" "$actual" 0
3739
fi
3840
}
3941

@@ -44,9 +46,9 @@ assert_is_error() {
4446
local message="$3"
4547

4648
if [[ "$actual" -eq "$expected" ]]; then
47-
print_success "$message"
49+
print_success "${FUNCNAME[0]}" "$message"
4850
else
49-
print_failure "$message" "$expected" "$actual" 1
51+
print_failure "${FUNCNAME[0]}" "$message" "$expected" "$actual" 1
5052
fi
5153
}
5254

@@ -56,8 +58,8 @@ assert_no_error() {
5658
local message="$2"
5759

5860
if [[ "$actual" -eq 0 ]]; then
59-
print_success "$message"
61+
print_success "${FUNCNAME[0]}" "$message"
6062
else
61-
print_failure "$message" "no error" "$actual" 1
63+
print_failure "${FUNCNAME[0]}" "$message" "no error" "$actual" 1
6264
fi
6365
}

logger.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
2-
# Set default log level to DEBUG if it's not already set
3-
: "${LOG_LEVEL:=DEBUG}"
2+
# Set default log level to INFO if it's not already set
3+
: "${LOG_LEVEL:=INFO}"
44
# Set default log enabled flag only if it's not been set before
55
: "${LOG_ENABLED:=1}"
66
# Set default log file if it's not already set

0 commit comments

Comments
 (0)