ip-wrangler 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []