pomelo-router 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODc0MzUwYWIxZWJhMWUwYzVmY2ZjNzkyNjk4ZWFlZGNiOTkzMmQwMg==
5
+ data.tar.gz: !binary |-
6
+ ZTAyMDU2ZmEyODkxMWQ5MjFkMWM1MmQxNGVjMzdjOGQyNGIyZjkyOQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YjY3MGQ2Njg3NGJiZjgyYTZlYWFiMGY4NGYxYjQxYTA5ZDU1ZjQwODk4YmI3
10
+ ZDNkYWI0NjI5NzI1ODZmNzhhZjA5NDY4ZjBlZjAzMjE4YTQ1ZjYyYWMzNTI0
11
+ NTM3Y2ZlYzU2Y2NkZmIyYTczMTk0NWI4N2QyODZiZTk2Njc1MGU=
12
+ data.tar.gz: !binary |-
13
+ MTNmZjdkMDg4OWE1MzBhNDJhOTZhMGE1MjU4MTYzOTBhZjFmNjg5MDFiZmQ3
14
+ OGEwODNkMTA0YzBkMmNkNTljMjg3NzY2NGE0NjI5YjAxOGU1MWEyYTZiNDU3
15
+ YjkyNzQzYzJlMmM5ZWVlMTc1NTliMDQ5MWRhNDk3MTIxYTAxOTk=
@@ -0,0 +1,6 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'pomelo'
4
+
5
+ p = Pomelo.from_argv(ARGV)
6
+ p.run
@@ -0,0 +1,85 @@
1
+ [networks]
2
+ # required, the loopback device, normally will be lo or lo0
3
+ loopback = "lo"
4
+ allow_icmp = true
5
+
6
+ [networks.internet]
7
+ ip = "111.111.111.111"
8
+ dev = "eth0"
9
+
10
+ [networks.locals]
11
+
12
+ [networks.locals.office]
13
+ net = "192.168.0.0/24"
14
+ dev = "eth1"
15
+ [networks.locals.guest]
16
+ net = "192.168.1.0/24"
17
+ dev = "eth1"
18
+
19
+ [networks.externals]
20
+ [networks.externals.vpn]
21
+ host = "192.168.99.2/24"
22
+ dev = "tun0"
23
+
24
+ # custom host/ip ranges definitions
25
+ [groups]
26
+ [groups.router]
27
+ host = "192.168.0.1"
28
+ [groups.www]
29
+ host = "192.168.0.2"
30
+ [groups.users]
31
+ range = "192.168.0.100-192.168.0.199"
32
+
33
+
34
+ [traffic]
35
+ # default iptables rule, allow or deny
36
+ # if you set this to be deny, you will
37
+ # have to manually set the ports
38
+ # in the ports section
39
+ global = "deny"
40
+
41
+
42
+ # openning ports on router
43
+ # not necessary when traffic.global is "allow"
44
+ [[ports]]
45
+ protocol = "tcp"
46
+ port = 22
47
+ dev = "eth0"
48
+ [[ports]]
49
+ protocol = "tcp"
50
+ port = 8080
51
+ dev = "eth0"
52
+ [[ports]]
53
+ protocol = "tcp"
54
+ port = 443
55
+ dev = "eth0"
56
+
57
+
58
+ # rules
59
+ [[rules]]
60
+ # access vpns for users
61
+ method = "gateway"
62
+ from = "#{groups.users}"
63
+ to = "#{networks.externals.vpn}"
64
+
65
+ # gateway settings
66
+ [[rules]]
67
+ method = "gateway"
68
+ from = "#{networks.locals.office}"
69
+ to = "#{networks.internet}"
70
+ [[rules]]
71
+ method = "gateway"
72
+ from = "#{networks.locals.guest}"
73
+ to = "#{networks.internet}"
74
+
75
+ # port forwarding
76
+ [[rules]]
77
+ method = "forward"
78
+ from = 8080
79
+ protocol = "tcp"
80
+ to = "#{groups.www.host}:80"
81
+ [[rules]]
82
+ method = "forward"
83
+ from = "50000:60000"
84
+ protocol = "tcp"
85
+ to = "#{groups.www.host}"
@@ -0,0 +1,9 @@
1
+ require 'pomelo/opts'
2
+ require 'pomelo/parser'
3
+
4
+ module Pomelo
5
+ def Pomelo.from_argv(argv)
6
+ opts = Opts.parse(argv)
7
+ return Parser.new(opts)
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ require 'optparse'
2
+ require 'optparse/time'
3
+ require 'ostruct'
4
+
5
+ module Pomelo
6
+ class Opts
7
+ def self.parse(args)
8
+ options = OpenStruct.new
9
+ options.mode = "run"
10
+ options.config_file = nil
11
+
12
+ opt = OptionParser.new do |opts|
13
+ opts.banner = "Usage: pomelo [-rp] path/to/config.yaml"
14
+ opts.separator ""
15
+ opts.separator "Specific options:"
16
+
17
+ opts.on("-r", "--run", "run commands") do
18
+ options.mode = "run"
19
+ end
20
+ opts.on("-p", "--print", "print commands") do
21
+ options.mode = "print"
22
+ end
23
+ opts.on("-c", "--configi [PATH]", String, "config file path") do |f|
24
+ options.config_file = f
25
+ end
26
+
27
+ opts.separator ""
28
+ opts.separator "Common options:"
29
+ opts.on_tail("-h", "--help", "Show help message") do
30
+ puts opts
31
+ exit
32
+ end
33
+ end
34
+
35
+ opt.parse!(args)
36
+ return options
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,158 @@
1
+ require 'toml'
2
+
3
+ module Pomelo
4
+ class Parser
5
+ def initialize(opts)
6
+ @opts = opts
7
+ @commands = []
8
+
9
+ @config = get_config
10
+ end
11
+
12
+ def parse
13
+ parse_routes
14
+ parse_iptables
15
+ end
16
+
17
+ def run
18
+ parse
19
+ run_commands = @commands.join("\n")
20
+ if print_only?
21
+ puts run_commands
22
+ else
23
+ system run_commands
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def print_only?
30
+ return @opts.mode == "print"
31
+ end
32
+
33
+ def get_config
34
+ config_file = @opts.config_file
35
+ unless config_file
36
+ puts "config file required"
37
+ exit
38
+ end
39
+
40
+ begin
41
+ config = TOML.load_file(config_file)
42
+ rescue Exception => e
43
+ puts e
44
+ puts e.backtrace.join("\n")
45
+ exit
46
+ end
47
+
48
+ return config
49
+ end
50
+
51
+ def parse_routes
52
+ end
53
+
54
+ def parse_iptables
55
+ init_iptables
56
+ open_ports
57
+ traffic_rules
58
+ end
59
+
60
+ def add_command(cmd)
61
+ @commands << cmd
62
+ end
63
+
64
+ def get_value(key)
65
+ parts = key.split "."
66
+ c = @config
67
+ parts.each do |p|
68
+ c = c[p]
69
+ end
70
+
71
+ # parsing quotes
72
+ c = parse_value(c) if c.is_a?(String)
73
+
74
+ return c
75
+ end
76
+
77
+ def parse_value(str)
78
+ return str.gsub(/\#\{([^\}]+)\}/) do |s|
79
+ a = s.gsub(/[\#\{\}]/, "")
80
+ return get_value(a)
81
+ end
82
+ end
83
+
84
+ def init_iptables
85
+ s = get_value("traffic.global") == "allow" ? "ACCEPT" : "DROP"
86
+ lo = get_value("networks.loopback")
87
+ add_command "iptables -F"
88
+ add_command "iptables -P INPUT #{s}"
89
+ add_command "iptables -P OUTPUT #{s}"
90
+ add_command "iptables -P FORWARD #{s}"
91
+ # allow loopback
92
+ add_command "iptables -A INPUT -i #{lo} -j ACCEPT"
93
+ add_command "iptables -A OUTPUT -o #{lo} -j ACCEPT"
94
+ # allow ping
95
+ if get_value("networks.allow_icmp")
96
+ add_command "iptables -A INPUT -p icmp -j ACCEPT"
97
+ add_command "iptables -A OUTPUT -p icmp -j ACCEPT"
98
+ end
99
+ end
100
+
101
+ def open_ports
102
+ get_value("ports").each do |p|
103
+ add_command "iptables -A INPUT -i #{p["dev"]} -p #{p["protocol"]} --dport #{p["port"]} -j ACCEPT"
104
+ add_command "iptables -A OUTPUT -o #{p["dev"]} -p #{p["protocol"]} --sport #{p["port"]} -j ACCEPT"
105
+ end
106
+ end
107
+
108
+ def traffic_rules
109
+ get_value("rules").each do |r|
110
+ parse_rule(r)
111
+ end
112
+ end
113
+
114
+ def parse_rule(r)
115
+ method = r["method"]
116
+ if method == "gateway"
117
+ parse_gateway_rule(r)
118
+ elsif method == "forward"
119
+ parse_forward_rule(r)
120
+ end
121
+ end
122
+
123
+ def parse_gateway_rule(r)
124
+ from = parse_value(r["from"])
125
+ to = parse_value(r["to"])
126
+ source = nil
127
+
128
+ if from["host"]
129
+ source = "-s #{from["host"]}"
130
+ elsif from["net"]
131
+ source = "-s #{from["net"]}"
132
+ elsif from["range"]
133
+ source = "-m iprange --src-range #{from["range"]}"
134
+ else
135
+ raise "from must contain host or range"
136
+ end
137
+
138
+ add_command "iptables -t nat -A POSTROUTING #{source} -o #{to["dev"]} -j MASQUERADE"
139
+ end
140
+
141
+ def parse_forward_rule(r)
142
+ from = r["from"]
143
+ protocol = r["protocol"] || "tcp"
144
+ # forward requires host for destination
145
+ to_host, to_port = parse_value(r["to"]).split(":")
146
+ if to_port
147
+ to = "#{to_host}:#{to_port}"
148
+ else
149
+ to_port = from
150
+ to = to_host
151
+ end
152
+
153
+ add_command "iptables -t nat -A PREROUTING -p #{protocol} --dport #{from} -j DNAT --to #{to}"
154
+ add_command "iptables -A FORWARD -p #{protocol} -d #{to_host} --dport #{to_port} -j ACCEPT"
155
+ end
156
+
157
+ end
158
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pomelo-router
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Leon Chen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: toml
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
27
+ description: linux router network setup automation
28
+ email: leonhart.chen@gmail.com
29
+ executables:
30
+ - pomelo
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/pomelo
35
+ - config.toml.example
36
+ - lib/pomelo.rb
37
+ - lib/pomelo/opts.rb
38
+ - lib/pomelo/parser.rb
39
+ homepage: https://github.com/leonchen/pomelo
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.4.6
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: pomelo-router
63
+ test_files: []