ip-wrangler 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 89f402bf64890c36deefd8756a91dcf31d077205
4
+ data.tar.gz: 48b32a9b15c002138927e8b345bf52d471c95486
5
+ SHA512:
6
+ metadata.gz: 3a0036134eb6ac45cfb8bfcb1daf2dfcdefb934d199cee57c3658e525793daafe4c220dc1ce7fb9cd1831757b5f8b5fbf899e8b974b2cb229f8d2d57a6a39d4b
7
+ data.tar.gz: 0d50e1f7dd64c0c948b030d53ee2df14a2dfd3dc40e3d7f2985f5c3c1e1d7f4decee390309a3ca6f4657d61b5f6c3562e571998d578c1abcb03d2d7254bddc50
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ .bundle/
2
+ vendor/
3
+
4
+ *.db
5
+ *.log
6
+ config.yml
7
+
8
+ .idea/
9
+ *.ipr
10
+ *.iws
11
+ *.iml
12
+
13
+ /nbproject/private/
14
+ /nbproject/
15
+
16
+ *.gem
data/.hound.yml ADDED
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ AllCops:
2
+ RunRailsCops: true
3
+
4
+ Metrics/LineLength:
5
+ Max: 99
6
+
7
+ StringLiterals:
8
+ EnforcedStyle: single_quotes
9
+ Enabled: true
data/CHANGELOG ADDED
@@ -0,0 +1,4 @@
1
+ v 0.1.0
2
+ - Migrate to gem structure
3
+ - Update documentation
4
+ - Add installation, configuration and services scripts
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ip-wrangler (0.1.0)
5
+ json (~> 1.8)
6
+ sequel (~> 4.19)
7
+ sinatra (~> 1.4)
8
+ sqlite3 (~> 1.3)
9
+ thin (~> 1.6)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ daemons (1.1.9)
15
+ eventmachine (1.0.6)
16
+ json (1.8.2)
17
+ rack (1.6.0)
18
+ rack-protection (1.5.3)
19
+ rack
20
+ rake (10.4.2)
21
+ sequel (4.19.0)
22
+ sinatra (1.4.5)
23
+ rack (~> 1.4)
24
+ rack-protection (~> 1.4)
25
+ tilt (~> 1.3, >= 1.3.4)
26
+ sqlite3 (1.3.10)
27
+ thin (1.6.3)
28
+ daemons (~> 1.0, >= 1.0.9)
29
+ eventmachine (~> 1.0)
30
+ rack (~> 1.0)
31
+ tilt (1.4.1)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ bundler (~> 1.6)
38
+ ip-wrangler!
39
+ rake (~> 10.4)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Paweł Suder
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/MANUAL.md ADDED
@@ -0,0 +1,14 @@
1
+ ## Manual installation
2
+
3
+ Install this software (as non-root):
4
+
5
+ git clone https://github.com/dice-cyfronet/ip-wrangler.git
6
+
7
+ Create gem locally (as non-root, inside project directory):
8
+
9
+ gem build ip-wrangler.gemspec
10
+
11
+ Install created gem:
12
+
13
+ gem install ip-wrangler-*.gem
14
+
data/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # IP Wrangler
2
+
3
+ [![Code Climate](https://codeclimate.com/github/dice-cyfronet/ip-wrangler/badges/gpa.svg)](https://codeclimate.com/github/dice-cyfronet/ip-wrangler)
4
+ [![Dependency Status](https://gemnasium.com/dice-cyfronet/ip-wrangler.svg)](https://gemnasium.com/dice-cyfronet/ip-wrangler)
5
+
6
+ In polish __Portostawiaczka__
7
+
8
+ This application manages DNAT port mappings and IP mappings for Virtual Machines
9
+ (behind the NAT). It needs to be run on a node which is a router for Virtual
10
+ Machines. It provides an API reachable via HTTP URL (`GET`, `POST`, `DELETE`)
11
+ which allows the user to perform changes on `iptables` `nat` tables. It manages
12
+ a pool of used and empty port mappings or IP mappings using an SQLite database.
13
+
14
+ ## Installation
15
+
16
+ ### Requirements
17
+
18
+ * `iptables`
19
+ * `lsof`
20
+ * `sudo` (the user which runs `ipwrangler` needs permissions to run `/sbin/iptables` and `/usr/bin/lsof` via `sudo`)
21
+ * `sqlite3` with `libsqlite3-dev`
22
+
23
+ ### Packages / Dependencies
24
+
25
+ Update your system (as root, **optional**):
26
+
27
+ aptitude update
28
+ aptitude upgrade
29
+
30
+ Install additional packages (as root, **optional**):
31
+
32
+ aptitude install iptables lsof sudo libsqlite3-dev g++ make autoconf bison build-essential libssl-dev libyaml-dev libreadline6 libreadline6-dev zlib1g zlib1g-dev
33
+
34
+ Install `ruby` and `bundler` (as root, **optional**):
35
+
36
+ mkdir /tmp/ruby
37
+ pushd /tmp/ruby
38
+ curl --progress http://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
39
+ pushd /tmp/ruby/ruby-2.1.2
40
+ ./configure --disable-install-rdoc
41
+ make
42
+ make install
43
+ gem install bundler --no-ri --no-rdoc
44
+ popd
45
+ popd
46
+
47
+ Install this software:
48
+
49
+ gem install ip-wrangler
50
+
51
+ Add `user_name` (which will start `ip-wrangler`) to `sudo` group (as root):
52
+
53
+ adduser user_name sudo
54
+
55
+ To enable `iptables` and `lsof` for user `user_name` modify `/etc/sudoers` (as root)
56
+ using `visudo`. Add the following line at the bottom of the file:
57
+
58
+ user_name host_name= NOPASSWD: /sbin/iptables, /usr/bin/lsof
59
+
60
+ `host_name` must be the same like in `/etc/hostname`.
61
+
62
+ ### Configuration
63
+
64
+ Before you start, configure *migratio* installation by executing short wizard:
65
+
66
+ ip-wrangler-configure ./config.yml
67
+
68
+ You may edit manually configuration file, eg. `config.yml`.
69
+
70
+ ### Run
71
+
72
+ When launching for the first time, run the application in the foreground:
73
+
74
+ ip-wrangler-start -c ./config.yml -F
75
+
76
+ Verify that everything is okay.
77
+
78
+ Application can be run in the background:
79
+
80
+ ip-wrangler-start -c ./config.yml -P ./ip-wrangler.pid
81
+
82
+ To stop `ipwrangler` which runs in the background:
83
+
84
+ ip-wrangler-stop -P ./ip-wrangler.pid
85
+
86
+ To clean rules created by `ipwrangler` in `iptables`:
87
+
88
+ ip-wrangler-clean <iptables_chain_name|maybe:IPT_WR>
89
+
90
+ You can use *init.d* scripts to start and stop *migratio* automatic. Check [`initd.md`](support/initd.md)
91
+
92
+ ### Log'n'roll
93
+
94
+ Use *logrotate* to roll generated logs. Example configuration for *logrotate*:
95
+
96
+ # ip-wrangler logrotate settings
97
+ # based on: http://stackoverflow.com/a/4883967
98
+
99
+ /path/to/ip-wrangler/src/log/*.log {
100
+ daily
101
+ missingok
102
+ rotate 90
103
+ compress
104
+ notifempty
105
+ copytruncate
106
+ }
107
+
108
+ ## API
109
+
110
+ ### Port
111
+
112
+ Listing:
113
+
114
+ * `GET /nat/port` - list all NAT port(s)
115
+ * `GET /nat/port/<private_ip>` - list NAT port(s) for specified private IP
116
+
117
+ Creating:
118
+
119
+ * `POST /nat/port/<private_ip>/<private_port>/<protocol>` - create NAT port for specified IP
120
+ * `POST /nat/port/<private_ip>/<private_port>` - create NAT ports (tcp,udp) for specified IP
121
+
122
+ Deleting:
123
+
124
+ * `DELETE /nat/port/<private_ip>/<private_port>/<protocol>` - delete NAT port with specified protocol for specified private IP
125
+ * `DELETE /nat/port/<private_ip>/<private_port` - delete NAT port for specified IP
126
+ * `DELETE /nat/port/<private_ip>` - delete any NAT port for specified IP
127
+
128
+ ### IP
129
+
130
+ Listing:
131
+
132
+ * `GET /nat/ip` - get list of all NAT IPs
133
+ * `GET /nat/ip/<private_ip>` - get list of NAT IPs for specified private IP
134
+
135
+ Creating:
136
+
137
+ * `POST /nat/ip/<private_ip>` - create NAT IP for specified private IP
138
+
139
+ Deleting:
140
+
141
+ * `DELETE /nat/ip/<private_ip>/<public_ip>` - delete NAT IP for specified private IP
142
+ * `DELETE /nat/ip/<private_ip>` - delete any NAT IP for specified private IP
143
+
144
+ ## API (old version)
145
+
146
+ Listing:
147
+
148
+ * `GET /` - get information about REST service
149
+ * `GET /dnat` - list all NAT port(s)
150
+ * `GET /dnat/<private_ip>` - list NAT port(s) for specified private IP
151
+
152
+ Creating:
153
+
154
+ * `POST /dnat/<private_ip>` - create NAT port for specified IP. The request body should be specified in the following format:
155
+
156
+ _example_
157
+
158
+ [
159
+ {
160
+ "port": 21,
161
+ "proto": tcp
162
+ },
163
+ {
164
+ "port": 22,
165
+ "proto": udp
166
+ }
167
+ ]
168
+
169
+ Deleting:
170
+
171
+ * `DELETE /dnat/<private_ip>/<private_port>/<protocol>` - delete NAT port with specified protocol for specified private IP
172
+ * `DELETE /dnat/<private_ip>/<private_port>` - delete NAT port for specified IP
173
+ * `DELETE /dnat/<private_ip>` - delete any NAT port for specified IP
174
+
175
+ ## Contributing
176
+
177
+ 1. Fork it!
178
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
179
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
180
+ 4. Push to the branch (`git push origin my-new-feature`)
181
+ 5. Create a new *Pull Request*
182
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ name = 'ip-wrangler'
4
+ gem = Gem::Specification.find_by_name(name)
5
+ command = File.join(gem.full_gem_path, 'bin/ip-wrangler-clean.sh')
6
+ system(command, *ARGV)
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+
3
+ if [ -z "$1" ]
4
+ then
5
+ echo "Usage: $(basename $0) <iptables_chain_name|maybe:IPT_WR>"
6
+ exit 1
7
+ fi
8
+
9
+ iptables_chain_name=$1
10
+
11
+ set -x
12
+
13
+ sudo /sbin/iptables -t nat --delete PREROUTING --jump ${iptables_chain_name}_PRE
14
+ sudo /sbin/iptables -t nat --delete POSTROUTING --jump ${iptables_chain_name}_POST
15
+ sudo /sbin/iptables -t nat --flush ${iptables_chain_name}_PRE
16
+ sudo /sbin/iptables -t nat --flush ${iptables_chain_name}_POST
17
+ sudo /sbin/iptables -t nat --delete-chain ${iptables_chain_name}_PRE
18
+ sudo /sbin/iptables -t nat --delete-chain ${iptables_chain_name}_POST
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ name = 'ip-wrangler'
4
+ gem = Gem::Specification.find_by_name(name)
5
+ command = File.join(gem.full_gem_path, 'bin/ip-wrangler-configure.sh')
6
+ system(command, *ARGV)
@@ -0,0 +1,78 @@
1
+ #!/bin/bash
2
+
3
+ export __dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
+ export __dir="$(dirname ${__dir})"
5
+
6
+ if [ -z "$1" ]
7
+ then
8
+ echo "Usage: $(basename $0) <path_to_config_file:maybe:config.yml>"
9
+ exit 1
10
+ fi
11
+
12
+ path_to_config_file=$1
13
+
14
+ echo "For more information, check: https://github.com/dice-cyfronet/ip-wrangler#configuration"
15
+
16
+ echo "====="
17
+
18
+ echo "Would like to override your current config with the default settings?"
19
+ cp -i ${__dir}/lib/config.yml.example ${path_to_config_file}
20
+
21
+ __log_dir="$(cat ${path_to_config_file} | grep log_dir: | awk '{print $2}')"
22
+ __db_path="$(cat ${path_to_config_file} | grep db_path: | awk '{print $2}')"
23
+ __username="$(cat ${path_to_config_file} | grep username: | awk '{print $2}')"
24
+ __password="$(cat ${path_to_config_file} | grep password: | awk '{print $2}')"
25
+ __iptables_chain_name="$(cat ${path_to_config_file} | grep iptables_chain_name: | awk '{print $2}')"
26
+ __ext_ip="$(cat ${path_to_config_file} | grep ext_ip: | awk '{print $2}')"
27
+ __port_ip="$(cat ${path_to_config_file} | grep port_ip: | awk '{print $2}')"
28
+ __port_start="$(cat ${path_to_config_file} | grep port_start: | awk '{print $2}')"
29
+ __port_stop="$(cat ${path_to_config_file} | grep port_stop: | awk '{print $2}')"
30
+
31
+ echo "====="
32
+
33
+ echo "Log directory (current value: \"${__log_dir}\", leave empty to use the same)"
34
+ read __new_log_dir
35
+ echo "Path to database file (current value: \"${__db_path}\", leave empty to use the same)"
36
+ read __new_db_path
37
+
38
+ echo "HTTP Username (current value: \"${__username}\", leave empty to use the same)"
39
+ read __new_username
40
+ echo "HTTP Password (current value: \"${__password}\", leave empty to use the same)"
41
+ read __new_password
42
+
43
+ echo "Iptables chains prefix (current value: \"${__iptables_chain_name}\", leave empty to use the same)"
44
+ read __new_iptables_chain_name
45
+
46
+ echo "External IP address user for NAT port. If your server is indicated by a different address than assigned to the outside interface, enter it here. (current value: \"${__ext_ip}\", leave empty to use the same)"
47
+ read __new_ext_ip
48
+ echo "Public IP address used for NAT port. Enter address which is assigned to the outside interface. (current value: \"${__port_ip}\", leave empty to use the same)"
49
+ read __new_port_ip
50
+ echo "First port in range of available ports for NAT (current value: \"${__port_start}\")"
51
+ read __new_port_start
52
+ echo "Last port in range of available ports for NAT (current value: \"${__port_stop}\")"
53
+ read __new_port_stop
54
+
55
+ echo "To update list of public IP used for NAT IP use your favorite text editor to edit \`${path_to_config_file}\`"
56
+
57
+ function check_and_replace() {
58
+ __new_value="__new_${1}"
59
+ __value="__${1}"
60
+ if [ ! -z "${!__new_value}" ] && [ "${!__value}" != "${!__new_value}" ]; then
61
+ sed -i "s#${1}:.*#${1}: ${!__new_value}#g" ${path_to_config_file}
62
+ fi
63
+ }
64
+
65
+ check_and_replace log_dir
66
+ check_and_replace db_path
67
+ check_and_replace username
68
+ check_and_replace password
69
+ check_and_replace iptables_chain_name
70
+ check_and_replace ext_ip
71
+ check_and_replace port_ip
72
+ check_and_replace port_start
73
+ check_and_replace port_stop
74
+
75
+ echo "====="
76
+ echo "Show ${path_to_config_file}. You may edit this file to add IP which will use to IP mapping."
77
+ echo "-----"
78
+ cat ${path_to_config_file}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ name = 'ip-wrangler'
4
+ gem = Gem::Specification.find_by_name(name)
5
+ command = File.join(gem.full_gem_path, 'bin/ip-wrangler-start.sh')
6
+ system(command, *ARGV)
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+
3
+ export __dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
+ export __dir=$( dirname ${__dir} )
5
+
6
+ export __port=8400
7
+ export __ip=0.0.0.0
8
+ export __tag=IpWrangler
9
+ export __daemon=-d
10
+
11
+ function usage() {
12
+ echo "Usage: $(basename $0) -c <config_file|maybe:config.yml> -P <pid_file|maybe:ip-wrangler.pid> -i <ip|default:0.0.0.0> -p <port|default:8400> -t <tag|default:IpWrangler> -F (foreground mode) -h (help and exit)"
13
+ }
14
+
15
+ while getopts 'c:P:i:p:t:Fh' __flag; do
16
+ case "${__flag}" in
17
+ c)
18
+ export __config_file="$(realpath ${OPTARG})"
19
+ ;;
20
+ P)
21
+ touch ${OPTARG}
22
+ export __pid_file="$(realpath ${OPTARG})"
23
+ rm ${OPTARG}
24
+ ;;
25
+ i)
26
+ export __ip=${OPTARG}
27
+ ;;
28
+ p)
29
+ export __port=${OPTARG}
30
+ ;;
31
+ t)
32
+ export __tag=${OPTARG}
33
+ ;;
34
+ F)
35
+ export __daemon=
36
+ export __no_log=1
37
+ ;;
38
+ h)
39
+ usage
40
+ exit 0
41
+ ;;
42
+ *)
43
+ error "Unexpected option: ${__flag}"
44
+ usage
45
+ exit 1
46
+ ;;
47
+ esac
48
+ done
49
+
50
+ if [ ! -z "${__daemon}" ] && [ -z "${__pid_file}" ]
51
+ then
52
+ echo "No PID file defined in daemon mode."
53
+ usage
54
+ exit 1
55
+ fi
56
+
57
+ if [ ! -z "${__pid_file}" ]
58
+ then
59
+ __pid_option="-P ${__pid_file}"
60
+ fi
61
+
62
+ if [ -z "${__config_file}" ]
63
+ then
64
+ echo "No config file defined."
65
+ usage
66
+ exit 1
67
+ fi
68
+
69
+ pushd ${__dir}/lib/ 2>&1 >> /dev/null
70
+ thin ${__daemon} ${__pid_option} -a ${__ip} -p ${__port} -R ./config.ru --tag ${__tag} start
71
+ popd 2>&1 >> /dev/null