ssh_tunnels 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.ruby-version +1 -1
- data/Gemfile +6 -0
- data/Gemfile.lock +45 -35
- data/README.md +16 -0
- data/bin/ssh_tunnels +7 -5
- data/lib/ssh_tunnels/tunnel.rb +29 -10
- data/lib/ssh_tunnels/ui.rb +8 -10
- data/lib/ssh_tunnels/version.rb +1 -1
- data/lib/ssh_tunnels.rb +1 -1
- data/ssh_tunnels.gemspec +6 -7
- metadata +20 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bcdb9b758ed9d27d0e81ba9bafbf8e50273fa38c2c954b332b916fccb7cc699
|
|
4
|
+
data.tar.gz: 42d49d0040704dbe2ca4c51040ccfffc797eb2f5cf4dbdc7c322aa51a9f26c27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 109da60813a282a22c54b91075112e9a2bf5408e2490abe7c625aae87ef7c45ef3633ab698cdfd5f82fa24cf2a0fae04e32a6c86ba9a66b275b2eba97621e4c3
|
|
7
|
+
data.tar.gz: 117a4e60567f1763cf7c55ca024e4a1a9fc00e4b187209aff3e57edb288b209dd18ab217e958d505a4837b5daab1a8bd9502e098d1640080c091633b60b6f282
|
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3.3.9
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,69 +1,79 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
ssh_tunnels (0.
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
ssh_tunnels (0.3.0)
|
|
5
|
+
bcrypt_pbkdf (~> 1.1)
|
|
6
|
+
curses (~> 1.4)
|
|
7
|
+
ed25519 (~> 1.3)
|
|
8
|
+
net-ssh (~> 7.0)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
9
11
|
remote: https://rubygems.org/
|
|
10
12
|
specs:
|
|
11
|
-
ast (2.4.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
ast (2.4.3)
|
|
14
|
+
bcrypt_pbkdf (1.1.2)
|
|
15
|
+
concurrent-ruby (1.3.6)
|
|
16
|
+
curses (1.6.0)
|
|
17
|
+
diff-lcs (1.6.2)
|
|
18
|
+
ed25519 (1.4.0)
|
|
19
|
+
i18n (1.14.8)
|
|
16
20
|
concurrent-ruby (~> 1.0)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
json (2.19.7)
|
|
22
|
+
language_server-protocol (3.17.0.5)
|
|
23
|
+
lint_roller (1.1.0)
|
|
24
|
+
net-ssh (7.3.2)
|
|
20
25
|
paint (2.3.0)
|
|
21
|
-
parallel (1.
|
|
22
|
-
parser (3.3.
|
|
26
|
+
parallel (2.1.0)
|
|
27
|
+
parser (3.3.11.1)
|
|
23
28
|
ast (~> 2.4.1)
|
|
24
29
|
racc
|
|
25
|
-
|
|
30
|
+
prism (1.9.0)
|
|
31
|
+
racc (1.8.1)
|
|
26
32
|
rainbow (3.1.1)
|
|
27
|
-
regexp_parser (2.
|
|
28
|
-
|
|
29
|
-
rspec (3.13.0)
|
|
33
|
+
regexp_parser (2.12.0)
|
|
34
|
+
rspec (3.13.2)
|
|
30
35
|
rspec-core (~> 3.13.0)
|
|
31
36
|
rspec-expectations (~> 3.13.0)
|
|
32
37
|
rspec-mocks (~> 3.13.0)
|
|
33
|
-
rspec-core (3.13.
|
|
38
|
+
rspec-core (3.13.6)
|
|
34
39
|
rspec-support (~> 3.13.0)
|
|
35
|
-
rspec-expectations (3.13.
|
|
40
|
+
rspec-expectations (3.13.5)
|
|
36
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
37
42
|
rspec-support (~> 3.13.0)
|
|
38
|
-
rspec-mocks (3.13.
|
|
43
|
+
rspec-mocks (3.13.8)
|
|
39
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
40
45
|
rspec-support (~> 3.13.0)
|
|
41
|
-
rspec-support (3.13.
|
|
42
|
-
rubocop (
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
rspec-support (3.13.7)
|
|
47
|
+
rubocop (1.86.2)
|
|
48
|
+
json (~> 2.3)
|
|
49
|
+
language_server-protocol (~> 3.17.0.2)
|
|
50
|
+
lint_roller (~> 1.1.0)
|
|
51
|
+
parallel (>= 1.10)
|
|
52
|
+
parser (>= 3.3.0.2)
|
|
45
53
|
rainbow (>= 2.2.2, < 4.0)
|
|
46
|
-
regexp_parser (>=
|
|
47
|
-
|
|
48
|
-
rubocop-ast (>= 0.0.3, < 1.0)
|
|
54
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
55
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
49
56
|
ruby-progressbar (~> 1.7)
|
|
50
|
-
unicode-display_width (>=
|
|
51
|
-
rubocop-ast (
|
|
52
|
-
parser (>=
|
|
57
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
58
|
+
rubocop-ast (1.49.1)
|
|
59
|
+
parser (>= 3.3.7.2)
|
|
60
|
+
prism (~> 1.7)
|
|
53
61
|
ruby-progressbar (1.13.0)
|
|
54
62
|
strong_versions (0.4.5)
|
|
55
63
|
i18n (>= 0.5)
|
|
56
64
|
paint (~> 2.0)
|
|
57
|
-
unicode-display_width (
|
|
65
|
+
unicode-display_width (3.2.0)
|
|
66
|
+
unicode-emoji (~> 4.1)
|
|
67
|
+
unicode-emoji (4.2.0)
|
|
58
68
|
|
|
59
69
|
PLATFORMS
|
|
60
70
|
ruby
|
|
61
71
|
|
|
62
72
|
DEPENDENCIES
|
|
63
|
-
rspec (~> 3.
|
|
64
|
-
rubocop (~>
|
|
73
|
+
rspec (~> 3.13)
|
|
74
|
+
rubocop (~> 1.86)
|
|
65
75
|
ssh_tunnels!
|
|
66
|
-
strong_versions (~> 0.4.
|
|
76
|
+
strong_versions (~> 0.4.5)
|
|
67
77
|
|
|
68
78
|
BUNDLED WITH
|
|
69
|
-
|
|
79
|
+
4.0.12
|
data/README.md
CHANGED
|
@@ -63,6 +63,17 @@ The `tunnels` section is a map where each key represents a named tunnel. Each tu
|
|
|
63
63
|
* `host`: The remote host to connect to from the gateway.
|
|
64
64
|
* `remote`: The remote port to use for forwarding.
|
|
65
65
|
* `local`: The local port to bind to (defaults to the `remote` port).
|
|
66
|
+
* `local_ip`: The local IP address to bind to (optional, defaults to the top-level `default_local_ip` if set, otherwise `127.0.0.1`). Equivalent to the `<local-ip>` component in `ssh -L <local-ip>:<local-port>:<remote-host>:<remote-port>`. Takes precedence over `default_local_ip`.
|
|
67
|
+
|
|
68
|
+
### Default local IP
|
|
69
|
+
|
|
70
|
+
The top-level `default_local_ip` option sets the local bind IP address used for all tunnels that do not specify their own `local_ip`:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
# config.yml
|
|
74
|
+
|
|
75
|
+
default_local_ip: 0.0.0.0
|
|
76
|
+
```
|
|
66
77
|
|
|
67
78
|
```yaml
|
|
68
79
|
# config.yml
|
|
@@ -85,6 +96,11 @@ tunnels:
|
|
|
85
96
|
local: 1111
|
|
86
97
|
host: other.host.example.com
|
|
87
98
|
remote: 5555
|
|
99
|
+
bound_host:
|
|
100
|
+
local_ip: 192.168.1.100
|
|
101
|
+
local: 2222
|
|
102
|
+
host: internal.host.example.com
|
|
103
|
+
remote: 8080
|
|
88
104
|
```
|
|
89
105
|
|
|
90
106
|
## Contributing
|
data/bin/ssh_tunnels
CHANGED
|
@@ -27,11 +27,12 @@ unless File.exist?(config_path)
|
|
|
27
27
|
exit 1
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
config = YAML.
|
|
30
|
+
config = YAML.safe_load_file(config_path)
|
|
31
31
|
|
|
32
32
|
begin
|
|
33
33
|
default_gateway = config.fetch('default_gateway', nil)
|
|
34
|
-
|
|
34
|
+
default_local_ip = config.fetch('default_local_ip', nil)
|
|
35
|
+
unless config.key?('tunnels')
|
|
35
36
|
warn('Configuration file must provide `tunnels` section. Exiting.')
|
|
36
37
|
exit 1
|
|
37
38
|
end
|
|
@@ -51,14 +52,14 @@ begin
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
if error
|
|
54
|
-
warn(
|
|
55
|
+
warn('Configuration errors detected. Exiting.')
|
|
55
56
|
exit 1
|
|
56
57
|
end
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
user = ENV.fetch('USER')
|
|
60
61
|
print 'Enter SSH key passphrase (leave blank if not required): '
|
|
61
|
-
passphrase =
|
|
62
|
+
passphrase = $stdin.noecho(&:gets).chomp
|
|
62
63
|
puts
|
|
63
64
|
|
|
64
65
|
begin
|
|
@@ -68,7 +69,8 @@ begin
|
|
|
68
69
|
else
|
|
69
70
|
default_gateway
|
|
70
71
|
end
|
|
71
|
-
|
|
72
|
+
config = { 'local_ip' => default_local_ip }.merge(tunnel_config)
|
|
73
|
+
SshTunnels::Tunnel.new(name, user, config, gateway, passphrase)
|
|
72
74
|
end
|
|
73
75
|
ui = SshTunnels::UI.new(tunnels)
|
|
74
76
|
ui.run
|
data/lib/ssh_tunnels/tunnel.rb
CHANGED
|
@@ -10,13 +10,18 @@ module SshTunnels
|
|
|
10
10
|
@user = user
|
|
11
11
|
@config = config
|
|
12
12
|
@passphrase = passphrase
|
|
13
|
-
@config = config
|
|
14
13
|
@gateway = gateway
|
|
15
|
-
@
|
|
14
|
+
@session = nil
|
|
15
|
+
@thread = nil
|
|
16
|
+
@active = false
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def to_s
|
|
19
|
-
base =
|
|
20
|
+
base = if local_host
|
|
21
|
+
"#{local_host}:#{local_port}:#{remote_host}:#{remote_port}"
|
|
22
|
+
else
|
|
23
|
+
"#{local_port}:#{remote_host}:#{remote_port}"
|
|
24
|
+
end
|
|
20
25
|
return base unless @error
|
|
21
26
|
|
|
22
27
|
"#{base} (#{@error})"
|
|
@@ -27,25 +32,35 @@ module SshTunnels
|
|
|
27
32
|
end
|
|
28
33
|
|
|
29
34
|
def open
|
|
30
|
-
@
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
@session = Net::SSH.start(@gateway.fetch('host'), @gateway.fetch('user', @user), options)
|
|
36
|
+
forward_local
|
|
37
|
+
@active = true
|
|
38
|
+
@thread = Thread.new { @session.loop(0.001) { @active } }
|
|
39
|
+
rescue StandardError
|
|
33
40
|
shutdown
|
|
34
41
|
raise
|
|
35
42
|
end
|
|
36
43
|
|
|
37
44
|
def active?
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@connection.active?
|
|
45
|
+
@active && @thread&.alive?
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
def shutdown
|
|
44
|
-
@
|
|
49
|
+
@active = false
|
|
50
|
+
@thread&.join
|
|
51
|
+
@session&.close
|
|
52
|
+
@session = nil
|
|
53
|
+
@thread = nil
|
|
45
54
|
end
|
|
46
55
|
|
|
47
56
|
private
|
|
48
57
|
|
|
58
|
+
def forward_local
|
|
59
|
+
args = [local_port, remote_host, remote_port]
|
|
60
|
+
args.unshift(local_host) if local_host
|
|
61
|
+
@session.forward.local(*args)
|
|
62
|
+
end
|
|
63
|
+
|
|
49
64
|
def remote_host
|
|
50
65
|
@config.fetch('host')
|
|
51
66
|
end
|
|
@@ -54,6 +69,10 @@ module SshTunnels
|
|
|
54
69
|
@config.fetch('remote_port')
|
|
55
70
|
end
|
|
56
71
|
|
|
72
|
+
def local_host
|
|
73
|
+
@config.fetch('local_ip', nil)
|
|
74
|
+
end
|
|
75
|
+
|
|
57
76
|
def local_port
|
|
58
77
|
@config.fetch('local_port', remote_port)
|
|
59
78
|
end
|
data/lib/ssh_tunnels/ui.rb
CHANGED
|
@@ -91,16 +91,14 @@ module SshTunnels
|
|
|
91
91
|
tunnel = @tunnels[IDENTIFIERS.index { |value| value == input }]
|
|
92
92
|
return status("Unrecognized tunnel: #{input}") if tunnel.nil?
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
status("Error: #{e}")
|
|
103
|
-
end
|
|
94
|
+
toggle_tunnel(tunnel)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def toggle_tunnel(tunnel)
|
|
98
|
+
status("#{tunnel.active? ? 'Disconnecting' : 'Connecting'}: #{tunnel}")
|
|
99
|
+
tunnel.toggle
|
|
100
|
+
rescue StandardError => e
|
|
101
|
+
status("Error: #{e}")
|
|
104
102
|
end
|
|
105
103
|
|
|
106
104
|
def tunnel_color(tunnel)
|
data/lib/ssh_tunnels/version.rb
CHANGED
data/lib/ssh_tunnels.rb
CHANGED
data/ssh_tunnels.gemspec
CHANGED
|
@@ -12,11 +12,12 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.description = 'Conveniently manage numerous SSH tunnels with ncurses'
|
|
13
13
|
spec.homepage = 'https://github.com/bobf/ssh_tunnels'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new('>=
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.3.0')
|
|
16
16
|
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
18
|
spec.metadata['source_code_uri'] = spec.homepage
|
|
19
19
|
spec.metadata['changelog_uri'] = 'https://github.com/bobf/ssh_tunnels/blob/master/CHANGELOG.md'
|
|
20
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
20
21
|
|
|
21
22
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
@@ -25,10 +26,8 @@ Gem::Specification.new do |spec|
|
|
|
25
26
|
spec.executables = 'ssh_tunnels'
|
|
26
27
|
spec.require_paths = ['lib']
|
|
27
28
|
|
|
28
|
-
spec.
|
|
29
|
-
spec.
|
|
30
|
-
|
|
31
|
-
spec.
|
|
32
|
-
spec.add_development_dependency 'rubocop', '~> 0.86.0'
|
|
33
|
-
spec.add_development_dependency 'strong_versions', '~> 0.4.4'
|
|
29
|
+
spec.add_dependency 'bcrypt_pbkdf', '~> 1.1'
|
|
30
|
+
spec.add_dependency 'curses', '~> 1.4'
|
|
31
|
+
spec.add_dependency 'ed25519', '~> 1.3'
|
|
32
|
+
spec.add_dependency 'net-ssh', '~> 7.0'
|
|
34
33
|
end
|
metadata
CHANGED
|
@@ -1,85 +1,71 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ssh_tunnels
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bob Farrell
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: bcrypt_pbkdf
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.
|
|
19
|
+
version: '1.1'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.
|
|
26
|
+
version: '1.1'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: curses
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '1.4'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rspec
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '3.9'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '3.9'
|
|
40
|
+
version: '1.4'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
42
|
+
name: ed25519
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
58
44
|
requirements:
|
|
59
45
|
- - "~>"
|
|
60
46
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
62
|
-
type: :
|
|
47
|
+
version: '1.3'
|
|
48
|
+
type: :runtime
|
|
63
49
|
prerelease: false
|
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
51
|
requirements:
|
|
66
52
|
- - "~>"
|
|
67
53
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
54
|
+
version: '1.3'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
56
|
+
name: net-ssh
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
72
58
|
requirements:
|
|
73
59
|
- - "~>"
|
|
74
60
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: 0
|
|
76
|
-
type: :
|
|
61
|
+
version: '7.0'
|
|
62
|
+
type: :runtime
|
|
77
63
|
prerelease: false
|
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
65
|
requirements:
|
|
80
66
|
- - "~>"
|
|
81
67
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: 0
|
|
68
|
+
version: '7.0'
|
|
83
69
|
description: Conveniently manage numerous SSH tunnels with ncurses
|
|
84
70
|
email:
|
|
85
71
|
- git@bob.frl
|
|
@@ -90,6 +76,7 @@ extra_rdoc_files: []
|
|
|
90
76
|
files:
|
|
91
77
|
- ".gitignore"
|
|
92
78
|
- ".rspec"
|
|
79
|
+
- ".rubocop.yml"
|
|
93
80
|
- ".ruby-version"
|
|
94
81
|
- Gemfile
|
|
95
82
|
- Gemfile.lock
|
|
@@ -113,6 +100,7 @@ metadata:
|
|
|
113
100
|
homepage_uri: https://github.com/bobf/ssh_tunnels
|
|
114
101
|
source_code_uri: https://github.com/bobf/ssh_tunnels
|
|
115
102
|
changelog_uri: https://github.com/bobf/ssh_tunnels/blob/master/CHANGELOG.md
|
|
103
|
+
rubygems_mfa_required: 'true'
|
|
116
104
|
post_install_message:
|
|
117
105
|
rdoc_options: []
|
|
118
106
|
require_paths:
|
|
@@ -121,14 +109,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
121
109
|
requirements:
|
|
122
110
|
- - ">="
|
|
123
111
|
- !ruby/object:Gem::Version
|
|
124
|
-
version:
|
|
112
|
+
version: 3.3.0
|
|
125
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
114
|
requirements:
|
|
127
115
|
- - ">="
|
|
128
116
|
- !ruby/object:Gem::Version
|
|
129
117
|
version: '0'
|
|
130
118
|
requirements: []
|
|
131
|
-
rubygems_version: 3.
|
|
119
|
+
rubygems_version: 3.5.22
|
|
132
120
|
signing_key:
|
|
133
121
|
specification_version: 4
|
|
134
122
|
summary: Interactive SSH tunnel management
|