stubby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +172 -111
- data/lib/stubby/cli/application.rb +1 -50
- data/lib/stubby/extensions/default.rb +72 -0
- data/lib/stubby/extensions/dns.rb +47 -30
- data/lib/stubby/extensions/http.rb +63 -26
- data/lib/stubby/extensions/smtp.rb +47 -0
- data/lib/stubby/kernel.rb +36 -0
- data/lib/stubby/master.rb +83 -42
- data/lib/stubby/process.rb +22 -0
- data/lib/stubby/registry.rb +16 -115
- data/lib/stubby/stub.rb +18 -6
- data/lib/stubby.rb +7 -0
- metadata +38 -2
data/LICENSE
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 James Kassemi, @Pay
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -20,17 +20,16 @@ from your project.
|
|
20
20
|
|
21
21
|
Install the stubby gem:
|
22
22
|
|
23
|
-
|
23
|
+
> $ sudo gem install stubby
|
24
24
|
|
25
25
|
## Available Options
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
> stubby status # View current rules
|
27
|
+
> $ sudo stubby -h
|
28
|
+
> Commands:
|
29
|
+
> stubby env NAME # Switch stubby environment
|
30
|
+
> stubby help [COMMAND] # Describe available commands or one specific command
|
31
|
+
> stubby start ENVIRONMENT # Starts stubby HTTP and DNS servers, default env ENVIRONMENT
|
32
|
+
> stubby status # View current rules
|
34
33
|
|
35
34
|
## Getting Started
|
36
35
|
|
@@ -38,72 +37,99 @@ Stubby uses `Stubfile.json` for configuration. This file includes a mapping of
|
|
38
37
|
environments to a number of rules that define server configurations and stub
|
39
38
|
usage for the project.
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
40
|
+
> cd ~/MyProject
|
41
|
+
> cat Stubfile.json
|
42
|
+
> {
|
43
|
+
> "test": {
|
44
|
+
> "dependencies": {
|
45
|
+
> "https://github.com/jkassemi/example-stubby.git": "staging"
|
46
|
+
> },
|
47
|
+
>
|
48
|
+
> "example.com": "localhost:3000"
|
49
|
+
> },
|
50
|
+
>
|
51
|
+
> "staging": {
|
52
|
+
> "dependencies": {
|
53
|
+
> "https://github.com/jkassemi/example-stubby.git": "staging"
|
54
|
+
> },
|
55
|
+
>
|
56
|
+
> "example.com": "dns-cname://aws..."
|
57
|
+
> }
|
58
|
+
> }
|
59
|
+
|
60
|
+
> $ sudo stubby start
|
62
61
|
|
63
62
|
The 'test' and 'staging' modes for this project both include rules for the
|
64
63
|
'example' stub, and then define a single rule of their own. Stubby starts
|
65
64
|
by default in the 'development' environment, so with this `Stubfile.json`,
|
66
65
|
the stubby server is not yet modifying any requests. In a new terminal:
|
67
66
|
|
68
|
-
|
67
|
+
> $ sudo stubby env test
|
69
68
|
|
70
69
|
Switches stubby to test mode. Now the 'example' stub is activated, and
|
71
70
|
additionally any requests to http or https versions of example.com are
|
72
71
|
routed to http://localhost:3000. Let's take a look at the rules applied:
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
73
|
+
> $ sudo bin/stubby status
|
74
|
+
|
75
|
+
> {
|
76
|
+
> "rules":{
|
77
|
+
> "https://github.com/jkassemi/example-stubby.git":{
|
78
|
+
> "dns://admin.example.com/a":"dns-a://172.16.123.1",
|
79
|
+
> "http://admin.example.com":"http-redirect://blank?to=https://admin.example.com&code=302",
|
80
|
+
> "https://admin.example.com":"http-proxy://10.0.1.1",
|
81
|
+
> "dns://admin2.example.com/a":"dns-cname://admin.example.com",
|
82
|
+
> "http://(.*)\\.?example.com":"http-proxy://10.0.1.1",
|
83
|
+
> "dns://(.*)\\.?example.com/a":"dns-a://172.16.123.1",
|
84
|
+
> "https://g?mail.*/.*":"http-proxy://en.wikipedia.org/wiki/RTFM",
|
85
|
+
> "dns://g?mail.*/.*/a":"dns-a://172.16.123.1",
|
86
|
+
> "http://yahoo.com":"http-redirect://duckduckgo.com",
|
87
|
+
> "dns://yahoo.com/a":"dns-a://172.16.123.1",
|
88
|
+
> "https://yahoo.com":"https-redirect://duckduckgo.com",
|
89
|
+
> "dns://.*\\.stubby.dev/a":"dns-a://172.16.123.1",
|
90
|
+
> "http://.*\\.stubby.dev":"file:///var/www/tmp",
|
91
|
+
> "https://.*\\.stubby.dev":"file:///var/www/tmp",
|
92
|
+
> "dns://api.example.com/a":"dns-a://172.16.123.1",
|
93
|
+
> "http://api.example.com":"file://~/.stubby/example/files",
|
94
|
+
> "https://api.example.com":"file://~/.stubby/example/files",
|
95
|
+
> "dns://.*/mx":"dns-mx://172.16.123.1/?priority=10"
|
96
|
+
> },
|
97
|
+
> "_":{
|
98
|
+
> "dependencies":{
|
99
|
+
> "https://github.com/jkassemi/example-stubby.git":"staging"
|
100
|
+
> },
|
101
|
+
> "dns://secured.atpay.com/a":"dns-a://172.16.123.1",
|
102
|
+
> "http://secured.atpay.com":"http-redirect://blank?to=https://secured.atpay.com&code=302",
|
103
|
+
> "https://secured.atpay.com":"http-proxy://localhost:3000",
|
104
|
+
> "dns://api.atpay.com/a":"dns-a://172.16.123.1",
|
105
|
+
> "http://api.atpay.com":"http-redirect://blank?to=https://api.atpay.com&code=302",
|
106
|
+
> "https://api.atpay.com":"http-proxy://localhost:4000",
|
107
|
+
> "dns://.*/mx":"dns-mx://172.16.123.1/?priority=10"
|
108
|
+
> },
|
109
|
+
> "_smtp":{
|
110
|
+
> "dns://outbox.stubby.dev/a":"dns-a://172.16.123.1",
|
111
|
+
> "http://outbox.stubby.dev":"http-proxy://172.16.123.1:9001"
|
112
|
+
> }
|
113
|
+
> },
|
114
|
+
> "environment":"development"
|
115
|
+
> }
|
98
116
|
|
99
117
|
This shows us all activated rules. the "_" indicates that the rules are loaded
|
100
|
-
from the current `Stubfile.json
|
101
|
-
|
118
|
+
from the current `Stubfile.json`, while "example" indicates that the rules are
|
119
|
+
loaded from an installed stub, "example".
|
102
120
|
|
103
121
|
To revert the system back to normal, just CTRL-C from the main stubby process.
|
104
122
|
This will revert any changes made to configure DNS servers for all network
|
105
123
|
interfaces and will shut down the stubby server.
|
106
124
|
|
125
|
+
### Stubs
|
126
|
+
|
127
|
+
- example: https://github.com/jkassemi/example-stubby.git
|
128
|
+
|
129
|
+
To contribute a stub, just add your stub to the list above and issue a pull
|
130
|
+
request.
|
131
|
+
|
132
|
+
|
107
133
|
## Stubbing
|
108
134
|
|
109
135
|
A stub is a folder named with the name of the stub that contains a stubby.json file. The stubby.json file contains a hash with the available
|
@@ -111,91 +137,94 @@ modes. Each mode contains a set of rules that define how to route DNS and how to
|
|
111
137
|
|
112
138
|
Installed stubs are in the ~/.stubby folder:
|
113
139
|
|
114
|
-
|
115
|
-
|
140
|
+
> $ ls ~/.stubby/jkassemi
|
141
|
+
> stubby-example
|
116
142
|
|
117
143
|
The example folder is the `example` stub, and the system.json file contains the agent configurations. You don't need to manually edit it.
|
118
144
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
145
|
+
> $ find ~/.stubby/jkassemi/example
|
146
|
+
> ... jkassemi/example
|
147
|
+
> ... jkassemi/example/files
|
148
|
+
> ... jkassemi/example/hello.html
|
149
|
+
> ... jkassemi/example/stubby.json
|
124
150
|
|
125
151
|
The example/stubby.json file has two modes, staging, and production:
|
126
152
|
|
127
|
-
|
128
|
-
|
153
|
+
> cat ~/.stubby/jkassemi/example-stubby/stubby.json
|
154
|
+
{ "staging": {...}, "production": {...} }
|
129
155
|
|
130
156
|
Each environment contains a number of rules:
|
131
157
|
|
132
|
-
|
133
|
-
|
134
|
-
|
158
|
+
{ "staging": {
|
159
|
+
"[PROTOCOL://]MATCH_REGEXP": "INSTRUCTION"
|
160
|
+
} ... }
|
135
161
|
|
136
162
|
When a request is made, either DNS or HTTP (important), the request is
|
137
|
-
compared against the
|
138
|
-
|
139
|
-
|
140
|
-
|
163
|
+
compared against the PROTOCOL and MATCH_REGEXP (together these are
|
164
|
+
called the TRIGGER). If matched, INSTRUCTION is executed.
|
165
|
+
Excluding a protocol from the trigger causes Stubby to presuppose a few
|
166
|
+
things about your request. It'll handle DNS, HTTP and HTTPS for definitions
|
167
|
+
like this.
|
141
168
|
|
142
|
-
|
169
|
+
"test.example.com": "http://10.0.1.5"
|
143
170
|
|
144
|
-
|
171
|
+
Expands to:
|
172
|
+
|
173
|
+
"dns://test.example.com/a": "dns-a://10.0.1.5",
|
174
|
+
"http://test.example.com": "http-redirect://blank?to=https://test.example.com&code=302",
|
175
|
+
"https://test.example.com": "http-proxy://10.0.1.5
|
176
|
+
|
177
|
+
Don't want to default over to https? You can be more explicit:
|
178
|
+
|
179
|
+
"http://test.example.com": "http://10.0.1.5"
|
180
|
+
|
181
|
+
Which expands to:
|
145
182
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
183
|
+
"dns://test.example.com/a": "dns-a://10.0.1.5",
|
184
|
+
"http://test.example.com": "http-proxy://10.0.1.5"
|
185
|
+
|
186
|
+
> $ dig test.example.com
|
187
|
+
...
|
188
|
+
;; ANSWER SECTION:
|
189
|
+
test.example.com. 0 IN A 172.16.123.1
|
150
190
|
|
151
|
-
172.16.123.1 is the stubby
|
191
|
+
172.16.123.1 is the stubby interface (TODO: configurable). All requests
|
152
192
|
to http://test.example.com are routed to the stubby web server at that
|
153
193
|
address.
|
154
194
|
|
155
|
-
|
156
|
-
|
157
|
-
Issues a request handled by the stubby web server, which proxies the request to 172.16.123.1.
|
195
|
+
> $ curl test.example.com
|
158
196
|
|
159
|
-
|
160
|
-
|
161
|
-
Fork this repository, update the index.json file, and submit a pull request. For
|
162
|
-
this major version, the remote registry will just be the index.json file from
|
163
|
-
this project's github.
|
197
|
+
Issues a request handled by the stubby web server, which proxies the request to 172.16.123.1.
|
164
198
|
|
165
199
|
### DNS Only
|
166
200
|
|
167
201
|
To simply override DNS for test.example.com, you can create an A record on lookup:
|
168
202
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
"test.example.com": "test.example2.com"
|
174
|
-
|
175
|
-
But you can be explicit in the INSTRUCTION:
|
203
|
+
"dns://test.example.com": "dns-a://10.0.1.5"
|
204
|
+
|
205
|
+
For a CNAME:
|
176
206
|
|
177
|
-
|
178
|
-
"test.example.com": "dns-cname://test.example2.com"
|
207
|
+
"dns://test.example.com": "dns-cname://test.example2.com"
|
179
208
|
|
180
209
|
Using the dns-#{name} convention, you can create simple references to
|
181
|
-
any dns record type.
|
182
|
-
|
210
|
+
any dns record type.
|
211
|
+
|
183
212
|
### File Server
|
184
213
|
|
185
214
|
Because stubby can intercept HTTP requests, it includes a base set of functionality that allows you two serve files directly from the stub. Given a rule:
|
186
215
|
|
187
|
-
|
216
|
+
"api.example.com": "file://~/.stubby/example/files"
|
188
217
|
|
189
218
|
DNS will resolve to the stubby server:
|
190
219
|
|
191
|
-
|
192
|
-
|
193
|
-
|
220
|
+
> $ dig api.example.com
|
221
|
+
...
|
222
|
+
api.example.com. 0 IN A 172.16.123.1
|
194
223
|
|
195
224
|
And a web request to api.example.com will serve files from the ~/.stubby/example/files directory:
|
196
225
|
|
197
|
-
|
198
|
-
|
226
|
+
> $ curl http://api.example.com/hello.html
|
227
|
+
> <html><head></head><body>Hello</body></html>
|
199
228
|
|
200
229
|
This is designed to allow you to create API stubs (success responses, for instance).
|
201
230
|
|
@@ -204,16 +233,48 @@ This is designed to allow you to create API stubs (success responses, for instan
|
|
204
233
|
|
205
234
|
Given a rule:
|
206
235
|
|
207
|
-
|
236
|
+
"http://yahoo.com": "http-redirect://blank?to=duckduckgo.com"
|
208
237
|
|
209
238
|
DNS will resolve to the stubby server, and the web request to http://yahoo.com will redirect to http://duckduckgo.com.
|
210
239
|
|
240
|
+
### Capturing Outgoing Email
|
241
|
+
|
242
|
+
Stubby includes an SMTP extension to capture outgoing messages. Specify the
|
243
|
+
domain to capture mail from and forward to smtp://
|
244
|
+
|
245
|
+
"smtp://.*\.example\.com": "about://blank"
|
246
|
+
|
247
|
+
will ensure any message sent by your system directly (this does not include
|
248
|
+
messages sent from yahoo or gmail) will be captured by Stubby. Visit
|
249
|
+
http://outbox.stubby.dev to see the captured messages.
|
250
|
+
|
251
|
+
Mail capture is currently provided by the "MailCatcher" gem.
|
252
|
+
|
211
253
|
### Vision
|
212
254
|
|
213
|
-
*
|
214
|
-
|
215
|
-
|
216
|
-
* proxy traffic on ports and send to log systems:
|
217
|
-
":25": "log-smtp://"
|
218
|
-
":3306": "log-mysql://"
|
255
|
+
* general traffic monitoring proxy traffic on ports and send to log systems:
|
256
|
+
":25": "smtp://"
|
257
|
+
":3306": "mysql://"
|
219
258
|
* web app front-end: show emails sent, mysql queries made, etc.
|
259
|
+
* github installation with no index.json
|
260
|
+
* P2P connections allow access to dev systems running stubby (agent mode?)
|
261
|
+
|
262
|
+
"example.com" => "localhost:3000"
|
263
|
+
"tunnel://example.com": "tunnel://jkassemi@stubby.site"
|
264
|
+
|
265
|
+
=>
|
266
|
+
|
267
|
+
On host system:
|
268
|
+
|
269
|
+
"example.com" => "localhost:3000"
|
270
|
+
|
271
|
+
On guest system:
|
272
|
+
|
273
|
+
"dns://example.com/.*" => @
|
274
|
+
"http://example.com" => "tunnel://jkassemi@stubby.site/?to=http://example.com"
|
275
|
+
"https://example.com" => "tunnel://jkassemi@stubby.site/?to=http://example.com"
|
276
|
+
"smtp://.*" => "tunnel://jkassemi@stubby.site/?to=smtp://$1"
|
277
|
+
|
278
|
+
|
279
|
+
guest opens a connection to stubby.site, requesting last broadcast of NAT address
|
280
|
+
for host. guest attempts udp tunnel with host
|
@@ -63,55 +63,6 @@ module Stubby
|
|
63
63
|
puts HTTPI.post("http://#{STUBBY_MASTER}:9000/environment.json", environment: name).body
|
64
64
|
end
|
65
65
|
|
66
|
-
desc "search", "View all available stubs"
|
67
|
-
long_desc <<-LONGDESC
|
68
|
-
View all available registered stubs. These are stubs that you can use
|
69
|
-
as dependencies in Stubfile.json.
|
70
|
-
|
71
|
-
> $ sudo stubby search
|
72
|
-
> {
|
73
|
-
> "example":[
|
74
|
-
> {
|
75
|
-
> "name":"example",
|
76
|
-
> "version":"v0.0.1",
|
77
|
-
> ...
|
78
|
-
> }
|
79
|
-
> ],
|
80
|
-
> "spreedly":[
|
81
|
-
> {
|
82
|
-
> "name":"spreedly",
|
83
|
-
> "version":"v0.0.1",
|
84
|
-
> ...
|
85
|
-
> }
|
86
|
-
> ]
|
87
|
-
> }
|
88
|
-
|
89
|
-
Wildcard supported for search:
|
90
|
-
|
91
|
-
> $ sudo stubby search ex*
|
92
|
-
> {
|
93
|
-
> "example":[
|
94
|
-
> {
|
95
|
-
> "name":"example",
|
96
|
-
> "version":"v0.0.1",
|
97
|
-
> ...
|
98
|
-
> }
|
99
|
-
> ]
|
100
|
-
> }
|
101
|
-
|
102
|
-
LONGDESC
|
103
|
-
def search(name=nil)
|
104
|
-
if master_running?
|
105
|
-
available = MultiJson.load(HTTPI.get("http://#{STUBBY_MASTER}:9000/stubs/available.json").body)
|
106
|
-
else
|
107
|
-
available = Stubby::Api.registry.index
|
108
|
-
end
|
109
|
-
|
110
|
-
puts MultiJson.dump(available.select { |key, ri|
|
111
|
-
File.fnmatch(name || "*", key)
|
112
|
-
}, pretty: true)
|
113
|
-
end
|
114
|
-
|
115
66
|
desc "status", "View current rules"
|
116
67
|
long_desc <<-LONGDESC
|
117
68
|
> $ sudo bin/stubby status
|
@@ -126,7 +77,7 @@ module Stubby
|
|
126
77
|
> "example":"staging"
|
127
78
|
> },
|
128
79
|
> "(https?://)?example.com":"http://localhost:3000"
|
129
|
-
>
|
80
|
+
> }
|
130
81
|
> },
|
131
82
|
> "environment":"test"
|
132
83
|
> }
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Extensions
|
2
|
+
class Default
|
3
|
+
def initialize
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
def run!(*args)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def stop!(*args)
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def expand_rule(trigger, instruction)
|
16
|
+
# Default expansion:
|
17
|
+
# "example.com": "localhost:3000"
|
18
|
+
#
|
19
|
+
# =>
|
20
|
+
# "dns://example.com": "@"
|
21
|
+
# "http://example.com": "http-redirect://blank?to=https://example.com&code=302"
|
22
|
+
# "https://example.com": "http-proxy://localhost:3000"
|
23
|
+
#
|
24
|
+
# "example.com:4000": "localhost:3000"
|
25
|
+
#
|
26
|
+
# =>
|
27
|
+
# ERROR: port in trigger unsupported
|
28
|
+
#
|
29
|
+
# "dns://example.com": "@"
|
30
|
+
# "http://example.com:4000"
|
31
|
+
#
|
32
|
+
# "example.com": "http-redirect://localhost:3000"
|
33
|
+
#
|
34
|
+
# =>
|
35
|
+
# "dns://example.com": "@"
|
36
|
+
# "http://example.com": "http-redirect://?blank?to=http://localhost:3000&code=302"
|
37
|
+
# =====================================
|
38
|
+
#
|
39
|
+
# ".*\\.stubby.dev": "file:///var/www/tmp
|
40
|
+
#
|
41
|
+
# =>
|
42
|
+
#
|
43
|
+
# "dns://.*\\.stubby.dev": "@",
|
44
|
+
# "http://.*\\.stubby.dev": "file:///var/www/tmp",
|
45
|
+
# "https://.*\\.stubby.dev": "file:///var/www/tmp",
|
46
|
+
scheme, remains = instruction.split("://")
|
47
|
+
scheme, remains = remains, scheme if remains.nil?
|
48
|
+
|
49
|
+
if scheme.nil?
|
50
|
+
expand_bare(trigger, instruction)
|
51
|
+
else
|
52
|
+
expand_with_protocol(trigger, instruction)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def expand_bare(trigger, instruction)
|
57
|
+
{
|
58
|
+
"dns://#{trigger}/a" => "dns-a://#{STUBBY_MASTER}",
|
59
|
+
"http://#{trigger}" => "http-redirect://blank?to=https://#{trigger}&code=302",
|
60
|
+
"https://#{trigger}" => "http-proxy://#{instruction}"
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def expand_with_protocol(trigger, instruction)
|
65
|
+
{
|
66
|
+
"dns://#{trigger}/a" => "dns-a://#{STUBBY_MASTER}",
|
67
|
+
"http://#{trigger}" => instruction,
|
68
|
+
"https://#{trigger}" => instruction
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -23,49 +23,46 @@ module Extensions
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def process(name, resource_class, transaction)
|
26
|
-
body = HTTPI.post("http://#{STUBBY_MASTER}:9000/rules/search.json",
|
26
|
+
body = HTTPI.post("http://#{STUBBY_MASTER}:9000/rules/search.json",
|
27
|
+
trigger: "dns://#{name}/#{symbol_from_resource_class(resource_class)}").body
|
27
28
|
|
28
29
|
instruction = MultiJson.load(body)
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
if instruction.nil? or instruction == "@"
|
32
|
+
transaction.passthrough!(UPSTREAM)
|
33
|
+
return
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
+
url = URI.parse(instruction)
|
36
37
|
|
37
|
-
|
38
|
-
url = URI.parse("dns-a://" + instruction)
|
39
|
-
elsif (url.scheme.to_s =~ /^dns-.*/).nil?
|
40
|
-
url.host = STUBBY_MASTER
|
41
|
-
end
|
38
|
+
response_resource_class = resource url.scheme.gsub('dns-', '')
|
42
39
|
|
43
|
-
|
40
|
+
if !IPAddress.valid?(url.host) and response_resource_class == IN::A
|
41
|
+
response_resource_class = IN::CNAME
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
url.host = STUBBY_MASTER
|
47
|
-
end
|
44
|
+
response = url.host
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
if [IN::CNAME, IN::MX].include? response_resource_class
|
47
|
+
response = Resolv::DNS::Name.create(url.host)
|
48
|
+
end
|
52
49
|
|
53
|
-
|
50
|
+
puts "DNS: #{name} => #{response}-#{resource_class.name})"
|
54
51
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
52
|
+
if response_resource_class == IN::MX
|
53
|
+
transaction.respond!(10, response,
|
54
|
+
:resource_class => response_resource_class,
|
55
|
+
:ttl => 0)
|
56
|
+
else
|
57
|
+
transaction.respond!(response,
|
58
|
+
:resource_class => response_resource_class,
|
59
|
+
:ttl => 0)
|
60
|
+
end
|
64
61
|
end
|
65
62
|
|
66
63
|
def run!(session, options)
|
67
64
|
return if options[:dns] == false
|
68
|
-
trap("INT"){ stop!
|
65
|
+
trap("INT"){ stop! }
|
69
66
|
|
70
67
|
@session = session
|
71
68
|
setup_references and run_dns_server
|
@@ -75,12 +72,32 @@ module Extensions
|
|
75
72
|
teardown_references and stop_dns_server
|
76
73
|
end
|
77
74
|
|
75
|
+
def expand_rule(trigger, instruction)
|
76
|
+
i = URI.parse(instruction)
|
77
|
+
t = URI.parse(trigger)
|
78
|
+
|
79
|
+
# If not specifying a record type, match a
|
80
|
+
t.path = "/a" if t.path.empty?
|
81
|
+
|
82
|
+
if i.scheme.nil?
|
83
|
+
{ t.to_s => "dns-a://#{instruction}" }
|
84
|
+
else
|
85
|
+
{ t.to_s => instruction }
|
86
|
+
end
|
87
|
+
end
|
78
88
|
|
79
89
|
private
|
80
90
|
|
81
91
|
def resource(pattern)
|
82
92
|
return IN::A unless pattern.respond_to? :to_sym
|
93
|
+
symbol_to_resource_class[pattern.to_sym] || IN::A
|
94
|
+
end
|
95
|
+
|
96
|
+
def symbol_from_resource_class(klass)
|
97
|
+
symbol_to_resource_class.invert[klass] || :a
|
98
|
+
end
|
83
99
|
|
100
|
+
def symbol_to_resource_class
|
84
101
|
{
|
85
102
|
a: IN::A,
|
86
103
|
aaaa: IN::AAAA,
|
@@ -93,7 +110,7 @@ module Extensions
|
|
93
110
|
soa: IN::SOA,
|
94
111
|
txt: IN::TXT,
|
95
112
|
cname: IN::CNAME
|
96
|
-
}
|
113
|
+
}
|
97
114
|
end
|
98
115
|
|
99
116
|
def run_dns_server
|