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.
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