netd_mngr 0.0.2
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 +7 -0
- data/bin/netc +125 -0
- data/bin/netd +46 -0
- data/lib/netd_core/netop.rb +103 -0
- data/lib/netd_core/request.rb +81 -0
- data/lib/netd_core.rb +116 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a1ec00680bcc40cc8eb18f09b108a04c26c7a7f0cbee12659bf4b503636bd724
|
4
|
+
data.tar.gz: 6c9b2fb762ef9fa0f5a204207df63eccb86a41c2f8ce018c418c19d89cab5938
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5cae0e347c02a7c1e265a3e1fe4d059b4a8e2dbb58debab4c8ab7dbe80532c205d74b4b6d2bef036e91c930d63ed9fdc6caee9f8272414e463d542d68193e6ff
|
7
|
+
data.tar.gz: '0817719f7dcb0ff40f0d7f869b488b20e07ad3590814c2c34710a29ac54310e601a7d4f4c0f7481062bfae069068f0cbec9fe8196a84bab5095889cc0ac2ead1'
|
data/bin/netc
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'netd_core'
|
5
|
+
require 'logger'
|
6
|
+
require 'zlib'
|
7
|
+
require 'base64'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
require 'dry/cli'
|
11
|
+
require 'awesome_print'
|
12
|
+
|
13
|
+
module NetC
|
14
|
+
# convention for dry/cli
|
15
|
+
module Command
|
16
|
+
# required to implement a cli command
|
17
|
+
extend Dry::CLI::Registry
|
18
|
+
|
19
|
+
# install the service file
|
20
|
+
class Install < Dry::CLI::Command
|
21
|
+
desc 'Install service file to systemd user directory'
|
22
|
+
def call(**)
|
23
|
+
# base64(zlib(netd.service))
|
24
|
+
service_file_data = 'eJwljLEKgzAURfd8RZaueUJnl2KHLl1EOohDjFcNvMby8pT69xW7He65nLZJUT' \
|
25
|
+
'tTIQeJH41LKpsMsYwNbA/aYoAdF7FPaGVMW/+nzty/CLV60ZLWLNTHRLL2u73M5HgJninPXkAT3qegqy' \
|
26
|
+
'tccf4SdDhSj5TVM3fm5ZNiuO3lgNGvrO7ITlDzAyzzNxM='
|
27
|
+
|
28
|
+
# reverse the encoding process for the systemd service file
|
29
|
+
service_file = Zlib::Inflate.inflate(Base64.decode64(service_file_data))
|
30
|
+
# path to install the file to
|
31
|
+
fname = "#{Dir.home}/.config/systemd/user/netd.service"
|
32
|
+
# write the decoded data to the file
|
33
|
+
File.write(fname, service_file)
|
34
|
+
|
35
|
+
# print install info
|
36
|
+
puts "Wrote service file to #{fname}"
|
37
|
+
puts "To enable the service, execute the following:\n"
|
38
|
+
puts 'systemctl --user enable netd.service'
|
39
|
+
puts 'systemctl --user start netd.service'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# list current forwards
|
44
|
+
class List < Dry::CLI::Command
|
45
|
+
# list current forwards
|
46
|
+
desc 'List the currently registered port forwards'
|
47
|
+
def call(**)
|
48
|
+
# open connection to server and
|
49
|
+
# dispatch the list command
|
50
|
+
NetDSvr.connect_to_netd do |socket|
|
51
|
+
socket.puts 'list|'
|
52
|
+
puts JSON.generate(NetDSvr.parse_list(socket))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module PortFwd
|
58
|
+
# Local port forward
|
59
|
+
class Local < Dry::CLI::Command
|
60
|
+
desc 'Create a new local port forward'
|
61
|
+
option :host, type: :String, default: '127.0.0.1', desc: 'Host address to bind to', required: true
|
62
|
+
option :bind, type: :String, default: '127.0.0.1:8000', desc: 'Host address to bind to in <ip>:<port> format'
|
63
|
+
option :remote, type: :String, desc: 'Remote address to connect to'
|
64
|
+
option :del, default: false, desc: 'Delete the specified forward'
|
65
|
+
|
66
|
+
def call(host:, bind:, remote:, del:, **)
|
67
|
+
# decode the bind host host_port pair
|
68
|
+
bind_addr, bind_port = bind.split(':')
|
69
|
+
# decode the remote host host_port pair
|
70
|
+
remote_addr, remote_port = remote.split(':')
|
71
|
+
# connect to server and send local forward request
|
72
|
+
NetDSvr.connect_to_netd do |socket|
|
73
|
+
if !del
|
74
|
+
socket.puts NetD::OperationRequest.local_port_forward(
|
75
|
+
host, bind_port.to_i, bind_addr, remote_port.to_i, remote_addr
|
76
|
+
)
|
77
|
+
else
|
78
|
+
socket.puts NetD::OperationRequest.delete_local_port_forward(host, remote_port.to_i, remote_addr)
|
79
|
+
end
|
80
|
+
puts socket.readline
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Remote port forward
|
86
|
+
class Remote < Dry::CLI::Command
|
87
|
+
desc 'Create a new remote port forward'
|
88
|
+
option :host, type: :String, default: '127.0.0.1', desc: 'Host address to bind to', required: true
|
89
|
+
option :bind, type: :String, default: '127.0.0.1:8000', desc: 'Remote address to bind to in <ip>:<port> format'
|
90
|
+
option :local, type: :String, desc: 'Local address to connect to'
|
91
|
+
option :del, default: false, desc: 'Delete the specified forward'
|
92
|
+
|
93
|
+
def call(host:, bind:, local:, del:, **)
|
94
|
+
# decode the remote bind host host_port pair
|
95
|
+
bind_addr, bind_port = bind.split(':')
|
96
|
+
# decode the local host host_port pair
|
97
|
+
local_addr, local_port = local.split(':')
|
98
|
+
# connect to server and send remote forward request
|
99
|
+
NetDSvr.connect_to_netd do |socket|
|
100
|
+
if !del
|
101
|
+
socket.puts NetD::OperationRequest.remote_port_forward(
|
102
|
+
host, bind_port.to_i, bind_addr, local_port.to_i, local_addr
|
103
|
+
)
|
104
|
+
else
|
105
|
+
socket.puts NetD::OperationRequest.delete_remote_port_forward(host, local_port.to_i, local_addr)
|
106
|
+
end
|
107
|
+
puts socket.readline
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
register 'install', Install
|
113
|
+
register 'list', List
|
114
|
+
register 'pfwd', aliases: ['p'] do |prefix|
|
115
|
+
prefix.register 'local', PortFwd::Local
|
116
|
+
prefix.register 'remote', PortFwd::Remote
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def main
|
122
|
+
Dry::CLI.new(NetC::Command).call
|
123
|
+
end
|
124
|
+
|
125
|
+
main
|
data/bin/netd
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'netd_core'
|
5
|
+
require 'logger'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
def detect_already_running(socket_path, logger)
|
9
|
+
# if the file does not exist, the server
|
10
|
+
# cannot be running
|
11
|
+
return unless File.exist?(socket_path)
|
12
|
+
|
13
|
+
# attempt to detect crash
|
14
|
+
logger.warn('Socket path exists, detecting crash')
|
15
|
+
# if the connection does not except,
|
16
|
+
# a server is running
|
17
|
+
begin
|
18
|
+
UNIXSocket.open(socket_path).close
|
19
|
+
# connection refused means server is not running
|
20
|
+
# so clean-up the old socket file
|
21
|
+
rescue Errno::ECONNREFUSED
|
22
|
+
logger.info('crash detected, cleaning up')
|
23
|
+
File.unlink(socket_path)
|
24
|
+
return
|
25
|
+
end
|
26
|
+
logger.fatal('Server appears to be running already')
|
27
|
+
end
|
28
|
+
|
29
|
+
def main
|
30
|
+
# setup logger
|
31
|
+
logger = Logger.new("#{Dir.home}/.local/share/netd.log")
|
32
|
+
logger.level = Logger::INFO
|
33
|
+
|
34
|
+
# setup and validate the unix socket path
|
35
|
+
socket_path = "#{Dir.home}/.local/run/"
|
36
|
+
Dir.mkdir(socket_path) unless Dir.exist?(socket_path)
|
37
|
+
socket_path += 'netd.socket'
|
38
|
+
|
39
|
+
detect_already_running(socket_path, logger)
|
40
|
+
|
41
|
+
# setup the server
|
42
|
+
server = NetDSvr.new(socket_path, logger)
|
43
|
+
server.server_main
|
44
|
+
end
|
45
|
+
|
46
|
+
main
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/ssh'
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
# netd namespace
|
7
|
+
module NetD
|
8
|
+
# encapsulates a currently running network operation
|
9
|
+
# Base Class
|
10
|
+
class NetworkOperation
|
11
|
+
attr_reader :request
|
12
|
+
attr_accessor :thread
|
13
|
+
|
14
|
+
def initialize(_request); end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
@request.values.join('|')
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
@thread.thread_variable_set('stop', true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# encapsulates a local port_forward
|
26
|
+
class LocalPortForward < NetworkOperation
|
27
|
+
def initialize(request)
|
28
|
+
super
|
29
|
+
@request = request
|
30
|
+
@thread = Thread.new(request) do |req|
|
31
|
+
stop = false
|
32
|
+
Net::SSH.start(req[:host], nil, keys_only: true) do |ssh|
|
33
|
+
ssh.forward.local(req[:bind_addr], req[:bind_port], req[:remote_addr], req[:remote_port])
|
34
|
+
ssh.loop(0.1) { true unless stop }
|
35
|
+
ssh.forward.cancel_local(req[:bind_port], req[:bind_addr])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# encapsulates a remote port_forward
|
42
|
+
class RemotePortForward < NetworkOperation
|
43
|
+
def initialize(request)
|
44
|
+
super
|
45
|
+
@request = request
|
46
|
+
@thread = Thread.new(request) do |req|
|
47
|
+
stop = false
|
48
|
+
Net::SSH.start(req[:host], nil, keys_only: true) do |ssh|
|
49
|
+
ssh.forward.remote(req[:bind_port], req[:bind_addr], req[:local_port], req[:local_addr])
|
50
|
+
ssh.loop(0.1) { true unless stop }
|
51
|
+
ssh.forward.cancel_remote(req[:bind_port], req[:bind_addr])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_forward
|
58
|
+
data = 'HELLO'
|
59
|
+
# create the server
|
60
|
+
TCPServer.open('127.0.0.1', 2224) do |svr|
|
61
|
+
# create the client
|
62
|
+
TCPSocket.open('127.0.0.1', 2222) do |c|
|
63
|
+
# accept the connection
|
64
|
+
s = svr.accept
|
65
|
+
# send a hello
|
66
|
+
c.puts data
|
67
|
+
# validate the data sent through
|
68
|
+
raise 'Forward test failed!!!' unless s.readline(chomp: true) == data
|
69
|
+
end
|
70
|
+
end
|
71
|
+
sleep(1) # let the threads complete
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_setup_port_forwards
|
75
|
+
lpfwd = LocalPortForward.new({ 'request': 'lpfwd',
|
76
|
+
'host': 'localhost',
|
77
|
+
'bind_port': 2222, 'bind_addr': 'localhost',
|
78
|
+
'remote_port': 2223, 'remote_addr': 'localhost' })
|
79
|
+
rpfwd = RemotePortForward.new({ 'request': 'rpfwd',
|
80
|
+
'host': 'localhost',
|
81
|
+
'bind_port': 2224, 'bind_addr': 'localhost',
|
82
|
+
'local_port': 2223, 'local_addr': 'localhost' })
|
83
|
+
sleep(1) # let the threads finish setting up
|
84
|
+
[lpfwd, rpfwd]
|
85
|
+
end
|
86
|
+
|
87
|
+
def test
|
88
|
+
puts 'testing forwards'
|
89
|
+
# setup the ssh-agent connector
|
90
|
+
Net::SSH::Authentication::Agent.connect(nil, nil, '/home/shellspawn/.1password/agent.sock')
|
91
|
+
# create the port forwards
|
92
|
+
lpfwd, rpfwd = test_setup_port_forwards
|
93
|
+
puts lpfwd, rpfwd
|
94
|
+
# send some data through the tunnel
|
95
|
+
test_forward
|
96
|
+
# close both forwards
|
97
|
+
[lpfwd, rpfwd].map(&:close)
|
98
|
+
puts 'all cleaned up'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# if ran independently, run tests
|
103
|
+
test if __FILE__ == $PROGRAM_NAME
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# parse requests from a pipe delimited line
|
4
|
+
module NetD
|
5
|
+
# encapsulate a request
|
6
|
+
class OperationRequest
|
7
|
+
LOCAL_PORT_FORWARD = 'lpfwd'
|
8
|
+
REMOTE_PORT_FORWARD = 'rpfwd'
|
9
|
+
DELETE_LOCAL_PORT_FORWARD = 'delete_lpfwd'
|
10
|
+
DELETE_REMOTE_PORT_FORWARD = 'delete_rpfwd'
|
11
|
+
LIST_FORWARDS = 'list'
|
12
|
+
|
13
|
+
def initialize(request_str)
|
14
|
+
malformed_request unless request_str.include? '|'
|
15
|
+
|
16
|
+
blocks = request_str.split('|')
|
17
|
+
@command = blocks[0]
|
18
|
+
@args = blocks[1..] if blocks.length > 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse
|
22
|
+
case @command
|
23
|
+
when LOCAL_PORT_FORWARD
|
24
|
+
pfwd_fmt(@command, 'local')
|
25
|
+
when REMOTE_PORT_FORWARD
|
26
|
+
pfwd_fmt(@command, 'remote')
|
27
|
+
when DELETE_LOCAL_PORT_FORWARD
|
28
|
+
del_pfwd_fmt(@command, 'local')
|
29
|
+
when DELETE_REMOTE_PORT_FORWARD
|
30
|
+
del_pfwd_fmt(@command, 'remote')
|
31
|
+
when LIST_FORWARDS
|
32
|
+
{ 'request': LIST_FORWARDS }
|
33
|
+
else
|
34
|
+
raise 'wat'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def pfwd_fmt(command, direction)
|
39
|
+
malformed_request unless @args.length == 5
|
40
|
+
lorr = direction == 'remote' ? 'local' : 'remote'
|
41
|
+
{
|
42
|
+
'request': command,
|
43
|
+
'host': @args[0],
|
44
|
+
'bind_addr': @args[1],
|
45
|
+
'bind_port': @args[2].to_i,
|
46
|
+
"#{lorr}_addr": @args[3],
|
47
|
+
"#{lorr}_port": @args[4].to_i
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def del_pfwd_fmt(command, direction)
|
52
|
+
lorr = direction == 'remote' ? 'local' : 'remote'
|
53
|
+
{
|
54
|
+
'request': command,
|
55
|
+
'host': @args[0],
|
56
|
+
"#{lorr}_addr": @args[1],
|
57
|
+
"#{lorr}_port": @args[2].to_i
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.local_port_forward(host, bind_port, bind_addr, remote_port, remote_addr)
|
62
|
+
"#{LOCAL_PORT_FORWARD}|#{host}|#{bind_addr}|#{bind_port}|#{remote_addr}|#{remote_port}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.remote_port_forward(host, bind_port, bind_addr, local_port, local_addr)
|
66
|
+
"#{REMOTE_PORT_FORWARD}|#{host}|#{bind_addr}|#{bind_port}|#{local_addr}|#{local_port}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.delete_local_port_forward(host, remote_port, remote_addr)
|
70
|
+
"#{DELETE_LOCAL_PORT_FORWARD}|#{host}|#{remote_addr}|#{remote_port}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.delete_remote_port_forward(host, local_port, local_addr)
|
74
|
+
"#{DELETE_REMOTE_PORT_FORWARD}|#{host}|#{local_addr}|#{local_port}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def malformed_request
|
78
|
+
raise 'malformed request'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/netd_core.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'netd_core/request'
|
4
|
+
require 'netd_core/netop'
|
5
|
+
|
6
|
+
# the server class of netd
|
7
|
+
class NetDSvr
|
8
|
+
# the server class of netd
|
9
|
+
def initialize(socket_path, logger)
|
10
|
+
@path = socket_path
|
11
|
+
@net_ops = []
|
12
|
+
@logger = logger
|
13
|
+
end
|
14
|
+
|
15
|
+
# standard connection to the netd.socket unix server
|
16
|
+
def self.connect_to_netd(&block)
|
17
|
+
# open the socket and execute the block
|
18
|
+
UNIXSocket.open("#{Dir.home}/.local/run/netd.socket", &block)
|
19
|
+
# if failed, print error
|
20
|
+
rescue Errno::ECONNREFUSED => e
|
21
|
+
puts "NetD server does not appear to be running #{e}"
|
22
|
+
end
|
23
|
+
|
24
|
+
# if local then the field is 'remote' if remote the command requires 'local'
|
25
|
+
def self.get_direction(command)
|
26
|
+
command == NetD::OperationRequest::LOCAL_PORT_FORWARD ? 'remote' : 'local'
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse_line(line)
|
30
|
+
tokens = line.split('|')
|
31
|
+
# common to both commands
|
32
|
+
req = { 'request': tokens[0], 'host': tokens[1], 'bind_addr': tokens[2], 'bind_port': tokens[3] }
|
33
|
+
# detect last line
|
34
|
+
return if tokens[0] == 'OKAY'
|
35
|
+
|
36
|
+
# add the fields to the output
|
37
|
+
direction = NetDSvr.get_direction(tokens[0])
|
38
|
+
req["#{direction}_addr"] = tokens[4]
|
39
|
+
req["#{direction}_port"] = tokens[5]
|
40
|
+
req
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.parse_list(sock)
|
44
|
+
# parse the first line (number of entries)
|
45
|
+
entries = []
|
46
|
+
number_of_lines = sock.readline.chomp[0..-2].to_i
|
47
|
+
number_of_lines.times do
|
48
|
+
# pretty print the hash result from parse_line
|
49
|
+
entries << NetDSvr.parse_line(sock.readline.chomp)
|
50
|
+
end
|
51
|
+
entries
|
52
|
+
end
|
53
|
+
|
54
|
+
def current_net_ops
|
55
|
+
# get a list of the commands used
|
56
|
+
# to dispatch the network operations
|
57
|
+
@net_ops.map(&:request).map { |v| v.values.join('|') }
|
58
|
+
end
|
59
|
+
|
60
|
+
def del_request(request_args)
|
61
|
+
@net_ops.each do |n|
|
62
|
+
case request_args[:request]
|
63
|
+
when NetD::OperationRequest::DELETE_LOCAL_PORT_FORWARD
|
64
|
+
if (n.request[:remote_addr] == request_args[:remote_addr]) && (n.request[:remote_port] == request_args[:remote_port])
|
65
|
+
n.close
|
66
|
+
@net_ops.delete(n)
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
when NetD::OperationRequest::DELETE_REMOTE_PORT_FORWARD
|
70
|
+
if (n.request[:local_addr] == request_args[:local_addr]) && (n.request[:local_port] == request_args[:local_port])
|
71
|
+
n.close
|
72
|
+
@net_ops.delete(n)
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def dispatch_command(request_args, server_socket)
|
81
|
+
# switch on the request type, dispatch the request,
|
82
|
+
# and add the object to the tracking list
|
83
|
+
case request_args[:request]
|
84
|
+
when NetD::OperationRequest::LOCAL_PORT_FORWARD
|
85
|
+
@net_ops << NetD::LocalPortForward.new(request_args)
|
86
|
+
when NetD::OperationRequest::REMOTE_PORT_FORWARD
|
87
|
+
@net_ops << NetD::RemotePortForward.new(request_args)
|
88
|
+
when NetD::OperationRequest::DELETE_LOCAL_PORT_FORWARD
|
89
|
+
del_request(request_args)
|
90
|
+
when NetD::OperationRequest::DELETE_REMOTE_PORT_FORWARD
|
91
|
+
del_request(request_args)
|
92
|
+
when NetD::OperationRequest::LIST_FORWARDS
|
93
|
+
server_socket.puts("#{current_net_ops.length}|\n#{current_net_ops.join("\n")}")
|
94
|
+
else
|
95
|
+
raise 'how did you get here?'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def server_main
|
100
|
+
UNIXServer.open(@path) do |serv|
|
101
|
+
# accept, dispatch, respond for all connections
|
102
|
+
loop do
|
103
|
+
# accept new connection
|
104
|
+
server_socket = serv.accept
|
105
|
+
# read command, parse it, and dispatch it
|
106
|
+
dispatch_command(NetD::OperationRequest.new(server_socket.readline).parse, server_socket)
|
107
|
+
# respond with success
|
108
|
+
server_socket.puts 'OKAY|'
|
109
|
+
rescue EOFError, Errno::EPIPE, RuntimeError => e
|
110
|
+
# if connection fails or bad data is sent, report error
|
111
|
+
@logger.error("Malformed Request: #{e.message}\n#{e.backtrace} ")
|
112
|
+
server_socket.puts 'ERR|' unless server_socket.closed?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: netd_mngr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- shellspawn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: cnetd is a small userspace server that allows for cnet to request port
|
14
|
+
forwards and other services
|
15
|
+
email: shellspawn@protonmail.com
|
16
|
+
executables:
|
17
|
+
- netd
|
18
|
+
- netc
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- bin/netc
|
23
|
+
- bin/netd
|
24
|
+
- lib/netd_core.rb
|
25
|
+
- lib/netd_core/netop.rb
|
26
|
+
- lib/netd_core/request.rb
|
27
|
+
homepage:
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 3.0.0
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.2.33
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: Server used for background port fwds
|
50
|
+
test_files: []
|