ip-wrangler 0.1.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.
@@ -0,0 +1,130 @@
1
+ module IpWrangler
2
+ class NAT
3
+ $lsof_bin_path = '/usr/bin/sudo /usr/bin/lsof'
4
+
5
+ def initialize(config, logger)
6
+ @config = config
7
+ @db = DB.new(config['db_path'], logger)
8
+ @iptables = Iptables.new($config['iptables_chain_name'], logger)
9
+ @logger = logger
10
+
11
+ @db.select_nat_port.each do |nat_port|
12
+ @iptables.append_nat_port(nat_port[:public_ip], nat_port[:public_port],
13
+ nat_port[:private_ip], nat_port[:private_port],
14
+ nat_port[:protocol])
15
+ end
16
+ @db.select_nat_ip.each do |nat_ip|
17
+ @iptables.append_nat_ip(nat_ip[:public_ip], nat_ip[:private_ip])
18
+ end
19
+ end
20
+
21
+ def not_used_port?(public_ip, public_port, protocol)
22
+ command = "#{$lsof_bin_path} -i #{protocol}@#{public_ip}:#{public_port}"
23
+ output = IpWrangler::Exec.execute_command(command)
24
+ output.empty?
25
+ end
26
+
27
+ def not_used_ip?(public_ip)
28
+ command = "#{$lsof_bin_path} -i @#{public_ip}"
29
+ output = IpWrangler::Exec.execute_command(command)
30
+ output.empty?
31
+ end
32
+
33
+ def find_port(private_ip, private_port, protocol)
34
+ port = @db.get_first_empty_nat_port(protocol)
35
+ if port
36
+ public_port = port[:public_port]
37
+ if not_used_port?(@config['port_ip'], public_port, protocol) &&
38
+ @iptables.not_exists_nat_port?(@config['port_ip'], public_port,
39
+ protocol, private_ip, private_port)
40
+ return @config['port_ip'], public_port
41
+ end
42
+ end
43
+ nil
44
+ end
45
+
46
+ def find_ip(private_ip)
47
+ ip = @db.get_first_empty_nat_ip
48
+ if ip
49
+ public_ip = ip[:public_ip]
50
+ if not_used_ip?(public_ip) &&
51
+ @iptables.not_exists_nat_ip?(public_ip, private_ip)
52
+ return public_ip
53
+ end
54
+ end
55
+ nil
56
+ end
57
+
58
+ def get_nat_ports(private_ip = nil)
59
+ @db.select_nat_port(private_ip)
60
+ end
61
+
62
+ def get_nat_ips(private_ip = nil)
63
+ @db.select_nat_ip(private_ip)
64
+ end
65
+
66
+ def lock_port(private_ip, private_port, protocol)
67
+ port = @db.select_nat_port(private_ip, private_port, protocol)
68
+ if port.empty?
69
+ public_ip, public_port = find_port(private_ip, private_port, protocol)
70
+ if public_ip && public_port
71
+ @db.insert_nat_port(public_ip, public_port,
72
+ private_ip, private_port, protocol)
73
+ @iptables.append_nat_port(public_ip, public_port,
74
+ private_ip, private_port, protocol)
75
+ { public_ip: public_ip, public_port: public_port,
76
+ private_ip: private_ip, private_port: private_port,
77
+ protocol: protocol }
78
+ end
79
+ else
80
+ port = port.to_a[0]
81
+ { public_ip: port[:public_ip], public_port: port[:public_port],
82
+ private_ip: private_ip, private_port: private_port,
83
+ protocol: port[:protocol] }
84
+ end
85
+ end
86
+
87
+ def lock_ip(private_ip)
88
+ ip = @db.select_nat_ip(private_ip)
89
+ if ip.empty?
90
+ public_ip = find_ip(private_ip)
91
+ if public_ip
92
+ @db.insert_nat_ip(public_ip, private_ip)
93
+ @iptables.append_nat_ip(public_ip, private_ip)
94
+ { public_ip: public_ip,
95
+ private_ip: private_ip }
96
+ end
97
+ else
98
+ ip = ip.to_a[0]
99
+ { public_ip: ip[:public_ip],
100
+ private_ip: private_ip }
101
+ end
102
+ end
103
+
104
+ def release_port(private_ip, private_port = nil, protocol = nil)
105
+ released_port = []
106
+ @db.select_nat_port(private_ip, private_port, protocol).each do |nat_port|
107
+ @iptables.delete_nat_port(nat_port[:public_ip], nat_port[:public_port],
108
+ nat_port[:private_ip], nat_port[:private_port],
109
+ nat_port[:protocol])
110
+ released_port.push({ public_ip: nat_port[:public_ip],
111
+ public_port: nat_port[:public_port],
112
+ private_ip: nat_port[:private_ip],
113
+ private_port: nat_port[:private_port],
114
+ protocol: nat_port[:protocol] })
115
+ end
116
+ @db.delete_nat_port(private_ip, private_port, protocol)
117
+ released_port
118
+ end
119
+
120
+ def release_ip(private_ip, public_ip = nil)
121
+ released_ip = []
122
+ @db.select_nat_ip(private_ip, public_ip).each do |nat_ip|
123
+ @iptables.delete_nat_ip(nat_ip[:public_ip], nat_ip[:private_ip])
124
+ released_ip.push({ public_ip: nat_ip[:public_ip] })
125
+ end
126
+ @db.delete_nat_ip(private_ip, public_ip)
127
+ released_ip
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,3 @@
1
+ module IpWrangler
2
+ VERSION = '0.1.0'
3
+ end
data/support/initd.md ADDED
@@ -0,0 +1,22 @@
1
+ ## Init.d
2
+
3
+ Download [`ip-wrangler`](https://github.com/dice-cyfronet/ip-wrangler/blob/master/support/initd/ip-wrangler)
4
+ into `/etc/init.d/ip-wrangler`.
5
+
6
+ wget -O /etc/init.d/ip-wrangler https://raw.githubusercontent.com/dice-cyfronet/ip-wrangler/master/support/initd/ip-wrangler
7
+ chmod +x /etc/init.d/ip-wrangler
8
+
9
+ Create directories:
10
+
11
+ mkdir /var/log/ip-wrangler /etc/ip-wrangler
12
+
13
+ Create configuration file in `/etc/ip-wrangler/ip-wrangler.yml` by
14
+
15
+ ip-wrangler-configure /etc/ip-wrangler/ip-wrangler.yml
16
+
17
+ Set values to:
18
+
19
+ * log directory: `/var/log/ip-wrangler`
20
+ * database file: `/etc/ip-wrangler/ip-wrangler.db`
21
+
22
+ Update your `initd` configuration to enable start and stop service. `ip-wrangler` will started by `root`.
@@ -0,0 +1,53 @@
1
+ #!/bin/sh
2
+ ### BEGIN INIT INFO
3
+ # Provides: ip-wrangler
4
+ # Required-Start: $local_fs $network $named $time $syslog
5
+ # Required-Stop: $local_fs $network $named $time $syslog
6
+ # Default-Start: 2 3 4 5
7
+ # Default-Stop: 0 1 6
8
+ # Description: Manage IP and port mapping.
9
+ ### END INIT INFO
10
+
11
+ PIDFILE=/var/run/ip-wrangler.pid
12
+ CONFIGFILE=/etc/ip-wrangler/ip-wrangler.yml
13
+
14
+ start() {
15
+ if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE); then
16
+ echo 'Service already running' >&2
17
+ return 1
18
+ fi
19
+ echo 'Starting service...' >&2
20
+ ip-wrangler-start -c $CONFIGFILE -P $PIDFILE
21
+ echo 'Service started' >&2
22
+ }
23
+
24
+ stop() {
25
+ if [ ! -f $PIDFILE ] || ! kill -0 $(cat $PIDFILE); then
26
+ echo 'Service not running' >&2
27
+ return 1
28
+ fi
29
+ echo 'Stopping service...' >&2
30
+ ip-wrangler-stop -P $PIDFILE
31
+ echo 'Service stopped' >&2
32
+ }
33
+
34
+ if [ ! -f $CONFIGFILE ]; then
35
+ echo "Config $CONFIGFILE not found" >&2
36
+ exit 1
37
+ fi
38
+
39
+ case "$1" in
40
+ start)
41
+ start
42
+ ;;
43
+ stop)
44
+ stop
45
+ ;;
46
+ restart)
47
+ stop
48
+ sleep 1
49
+ start
50
+ ;;
51
+ *)
52
+ echo "Usage: $0 {start|stop|restart}"
53
+ esac
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ip-wrangler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Paweł Suder
8
+ - Jan Meizner
9
+ - Bartosz Wilk
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-02-11 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.4'
29
+ - !ruby/object:Gem::Dependency
30
+ name: thin
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '1.6'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.6'
43
+ - !ruby/object:Gem::Dependency
44
+ name: sequel
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '4.19'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '4.19'
57
+ - !ruby/object:Gem::Dependency
58
+ name: sqlite3
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '1.3'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.3'
71
+ - !ruby/object:Gem::Dependency
72
+ name: json
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '1.8'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '1.8'
85
+ - !ruby/object:Gem::Dependency
86
+ name: bundler
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '1.6'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '1.6'
99
+ - !ruby/object:Gem::Dependency
100
+ name: rake
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '10.4'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '10.4'
113
+ description: Iptables DNAT manager
114
+ email:
115
+ - pawel@suder.info
116
+ - j.meizner@cyfronet.pl
117
+ - b.wilk@cyfronet.pl
118
+ executables:
119
+ - ip-wrangler-clean
120
+ - ip-wrangler-clean.sh
121
+ - ip-wrangler-configure
122
+ - ip-wrangler-configure.sh
123
+ - ip-wrangler-start
124
+ - ip-wrangler-start.sh
125
+ - ip-wrangler-stop
126
+ - ip-wrangler-stop.sh
127
+ - ip-wrangler-test
128
+ - ip-wrangler-test.sh
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".hound.yml"
134
+ - ".rubocop.yml"
135
+ - CHANGELOG
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - LICENSE.txt
139
+ - MANUAL.md
140
+ - README.md
141
+ - Rakefile
142
+ - bin/ip-wrangler-clean
143
+ - bin/ip-wrangler-clean.sh
144
+ - bin/ip-wrangler-configure
145
+ - bin/ip-wrangler-configure.sh
146
+ - bin/ip-wrangler-start
147
+ - bin/ip-wrangler-start.sh
148
+ - bin/ip-wrangler-stop
149
+ - bin/ip-wrangler-stop.sh
150
+ - bin/ip-wrangler-test
151
+ - bin/ip-wrangler-test.sh
152
+ - ip-wrangler.gemspec
153
+ - lib/config.ru
154
+ - lib/config.yml.example
155
+ - lib/ip_wrangler/db.rb
156
+ - lib/ip_wrangler/exec.rb
157
+ - lib/ip_wrangler/ip.rb
158
+ - lib/ip_wrangler/iptables.rb
159
+ - lib/ip_wrangler/main.rb
160
+ - lib/ip_wrangler/nat.rb
161
+ - lib/ip_wrangler/version.rb
162
+ - support/initd.md
163
+ - support/initd/ip-wrangler
164
+ homepage: https://github.com/dice-cyfronet/ip-wrangler
165
+ licenses:
166
+ - MIT
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 2.2.2
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Service is responsible for managing DNAT rules in iptables nat table
188
+ test_files: []