pipe2me-client 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +29 -29
- data/lib/pipe2me/bin/natpmpc +337 -0
- data/lib/pipe2me/cli-foreman.rb +7 -3
- data/lib/pipe2me/cli-monit.rb +18 -12
- data/lib/pipe2me/cli.rb +14 -14
- data/lib/pipe2me/config.rb +1 -1
- data/lib/pipe2me/ext/http.rb +2 -2
- data/lib/pipe2me/ext/sys.rb +7 -7
- data/lib/pipe2me/tunnel/commands.rb +17 -8
- data/lib/pipe2me/tunnel/echo/http +1 -1
- data/lib/pipe2me/tunnel.rb +1 -1
- data/lib/pipe2me/version.rb +2 -2
- data/test/env-test.sh +1 -1
- data/test/monitrc-test.sh +1 -1
- data/test/opensslkey-test.sh +1 -1
- data/test/redirection-test.sh +1 -1
- data/test/setup-test.sh +5 -3
- data/test/sshkey-test.sh +1 -1
- data/test/testhelper.inc +1 -1
- data/test/testhelper.release +1 -1
- data/test/verify-test.sh +3 -3
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eceaa5c69187b15f7b43b0fe2cdbe1dd9b7281f
|
4
|
+
data.tar.gz: ca812510cb4937691876f1fc8b5642b50cea853d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee65b0e72ff5c66bb7bca14a7c2724a0e7f1717b33696d0b9aaf1aa1f7a87b1a8ea78cffab3f4d08df416a6dcf17c1f72d13db195a3be7037da69194193dedfe
|
7
|
+
data.tar.gz: 7fa92f1490c22365e4a8ca87f0ed4480429923694ba24d6c2ac897db6f37162ca64b1fc7493b67698342951d881364386aa6761d67afcc97cd958f127247dd90
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# pipe2me client
|
2
2
|
|
3
|
-
This is the ruby client for the pipe2me server package.
|
3
|
+
This is the ruby client for the pipe2me server package.
|
4
4
|
The pipe2me client lets you publish local services to the public internet
|
5
5
|
with the help and orchestration of a pipe2me server. For more details
|
6
6
|
see [pipe2me](https://github.com/kinko/pipe2me)
|
@@ -15,7 +15,7 @@ To install it run
|
|
15
15
|
sudo cp doc/pipe2me.1 /usr/local/share/man/man1
|
16
16
|
|
17
17
|
If you are managing a box with a system-wide ruby installation you must install
|
18
|
-
it via
|
18
|
+
it via
|
19
19
|
|
20
20
|
sudo gem install pipe2me-client
|
21
21
|
|
@@ -25,13 +25,13 @@ Verify the installation with
|
|
25
25
|
|
26
26
|
## Usage
|
27
27
|
|
28
|
-
Mini-example: This registers two tunnels with a single hostname for
|
29
|
-
two services on localhost (http on port 9090, https on port 9091).
|
28
|
+
Mini-example: This registers two tunnels with a single hostname for
|
29
|
+
two services on localhost (http on port 9090, https on port 9091).
|
30
30
|
|
31
31
|
<pre>
|
32
32
|
# Setup tunnels. This responds with the domain name
|
33
33
|
> <b>pipe2me setup --protocols http,https \
|
34
|
-
--server http://test.pipe2.me
|
34
|
+
--server http://test.pipe2.me \
|
35
35
|
--token review@pipe2me --ports 9090,9091</b>
|
36
36
|
pretty-ivory-horse.test.pipe2.me
|
37
37
|
|
@@ -44,31 +44,31 @@ PIPE2ME_URLS_1=https://pretty-ivory-horse.test.pipe2.me:10004
|
|
44
44
|
> <b>pipe2me start</b>
|
45
45
|
</pre>
|
46
46
|
|
47
|
-
See also the [example session](http://test.pipe2.me/example_session.html)
|
47
|
+
See also the [example session](http://test.pipe2.me/example_session.html)
|
48
48
|
and the [man page](http://test.pipe2.me/pipe2me.1.html).
|
49
49
|
|
50
50
|
## Testing
|
51
51
|
|
52
|
-
Tests are implemented using
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
Tests are implemented using roundup.
|
53
|
+
To install roundup on OSX, run `brew install roundup`. Other systems are
|
54
|
+
supported as well, [compare roundup's documentation](https://github.com/bmizerany/roundup/blob/master/INSTALLING#files)
|
55
|
+
for details.
|
56
56
|
|
57
|
-
The implemented tests are *integration tests* in the sense, that they test the
|
58
|
-
behaviour of the *pipe2me-client* package in connection to an external pipe2me
|
59
|
-
server. That means you should run a pipe2me server on your local machine. Note
|
57
|
+
The implemented tests are *integration tests* in the sense, that they test the
|
58
|
+
behaviour of the *pipe2me-client* package in connection to an external pipe2me
|
59
|
+
server. That means you should run a pipe2me server on your local machine. Note
|
60
60
|
that the server must be configured to support test mode. (In test mode a pipe2me
|
61
|
-
server accepts test auth tokens, that create short lived tunnels
|
62
|
-
with self-signed certificates.)
|
61
|
+
server accepts test auth tokens, that create short lived tunnels
|
62
|
+
with self-signed certificates.)
|
63
63
|
|
64
64
|
To run the tests against a locally installed test server run `rake`. Note that
|
65
65
|
the local test server is expected at "pipe2.dev:8080". You might have to adjust
|
66
|
-
the `/etc/hosts` file to add an entry
|
66
|
+
the `/etc/hosts` file to add an entry
|
67
67
|
|
68
68
|
127.0.0.1 pipe2.dev
|
69
69
|
|
70
|
-
Before submitting a pull request you should also run a test against the
|
71
|
-
test.pipe2.me instance, which is available most of the time for that purpose.
|
70
|
+
Before submitting a pull request you should also run a test against the
|
71
|
+
test.pipe2.me instance, which is available most of the time for that purpose.
|
72
72
|
To do that, run `rake test:release`.
|
73
73
|
|
74
74
|
## Tunnel tokens
|
@@ -76,9 +76,9 @@ To do that, run `rake test:release`.
|
|
76
76
|
As ports and domain names are sparse resources the pipe2me server API
|
77
77
|
requires the use of authorization tokens when requesting a tunnel. A
|
78
78
|
token is similar to a 'currency' in that it describes which tunnels are
|
79
|
-
supported. A token could limit the number of ports that can be tunnelled,
|
80
|
-
the amount of traffic for those ports, whether or not a certificate is
|
81
|
-
self-signed or signed by a regular CA, etc.
|
79
|
+
supported. A token could limit the number of ports that can be tunnelled,
|
80
|
+
the amount of traffic for those ports, whether or not a certificate is
|
81
|
+
self-signed or signed by a regular CA, etc.
|
82
82
|
|
83
83
|
|
84
84
|
The features of a token are not defined within this protocol. However,
|
@@ -87,24 +87,24 @@ to know more.
|
|
87
87
|
|
88
88
|
A freshly installed pipe2me server comes with a number of preconfigured tokens.
|
89
89
|
Of course, a server admin should (and probably would) change those tokens.
|
90
|
-
However, as a test target, the pipe2me test server at http://test.pipe2.me
|
91
|
-
supports these tokens:
|
90
|
+
However, as a test target, the pipe2me test server at http://test.pipe2.me
|
91
|
+
supports these tokens:
|
92
92
|
|
93
93
|
- `test@pipe2me`: this builds tunnels that are available for 5 minutes.
|
94
94
|
The test token is intended for use with automated test scenarios.
|
95
|
-
- `review@pipe2me`: this builds tunnels that are available for up to
|
95
|
+
- `review@pipe2me`: this builds tunnels that are available for up to
|
96
96
|
one day. A review token should help you get a feel for the pipe2me
|
97
|
-
package.
|
97
|
+
package.
|
98
98
|
|
99
|
-
If you need a longer lived token for development, review and/or test
|
100
|
-
feel free to contact us at contact@kinko.me.
|
99
|
+
If you need a longer lived token for development, review and/or test
|
100
|
+
feel free to contact us at contact@kinko.me.
|
101
101
|
|
102
102
|
## Licensing
|
103
103
|
|
104
|
-
**The pipe2me client software** is (c) The Kinko Team, 2014 and released to you
|
104
|
+
**The pipe2me client software** is (c) The Kinko Team, 2014 and released to you
|
105
105
|
under the terms of the MIT License (MIT), see COPYING.MIT for details.
|
106
106
|
|
107
107
|
The subdirectory lib/vendor contains third-party code, which is subject to its own copyrights.
|
108
108
|
Please see the respective source files for copyright information.
|
109
|
-
|
109
|
+
|
110
110
|
(c) The kinko team, 2014
|
@@ -0,0 +1,337 @@
|
|
1
|
+
#!/usr/bin/env jit cc -g -Werror -Wall -lnatpmp --
|
2
|
+
|
3
|
+
/* $Id: natpmpc.c,v 1.13 2012/08/21 17:23:38 nanard Exp $ */
|
4
|
+
/* libnatpmp
|
5
|
+
Copyright (c) 2007-2011, Thomas BERNARD
|
6
|
+
All rights reserved.
|
7
|
+
|
8
|
+
Redistribution and use in source and binary forms, with or without
|
9
|
+
modification, are permitted provided that the following conditions are met:
|
10
|
+
|
11
|
+
* Redistributions of source code must retain the above copyright notice,
|
12
|
+
this list of conditions and the following disclaimer.
|
13
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
14
|
+
this list of conditions and the following disclaimer in the documentation
|
15
|
+
and/or other materials provided with the distribution.
|
16
|
+
* The name of the author may not be used to endorse or promote products
|
17
|
+
derived from this software without specific prior written permission.
|
18
|
+
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*/
|
31
|
+
#include <stdio.h>
|
32
|
+
#include <stdlib.h>
|
33
|
+
#include <errno.h>
|
34
|
+
#include <string.h>
|
35
|
+
#if defined(_MSC_VER)
|
36
|
+
#if _MSC_VER >= 1400
|
37
|
+
#define strcasecmp _stricmp
|
38
|
+
#else
|
39
|
+
#define strcasecmp stricmp
|
40
|
+
#endif
|
41
|
+
#else
|
42
|
+
#include <unistd.h>
|
43
|
+
#endif
|
44
|
+
#ifdef WIN32
|
45
|
+
#include <winsock2.h>
|
46
|
+
#else
|
47
|
+
#include <netinet/in.h>
|
48
|
+
#include <arpa/inet.h>
|
49
|
+
#endif
|
50
|
+
|
51
|
+
// #define ENABLE_STRNATPMPERR
|
52
|
+
|
53
|
+
#include "natpmp.h"
|
54
|
+
|
55
|
+
static const char * argv0;
|
56
|
+
static FILE* debug;
|
57
|
+
|
58
|
+
static void usage()
|
59
|
+
{
|
60
|
+
fprintf(stderr, "Usage :\n");
|
61
|
+
fprintf(stderr, " %s [options]\n", argv0);
|
62
|
+
fprintf(stderr, "\tdisplay the public IP address.\n");
|
63
|
+
fprintf(stderr, " %s [options] [protcol:]<public port>[:<private port>] <public port>[:<private port>] ... \n", argv0);
|
64
|
+
fprintf(stderr, "\tadd map one or more ports. protocol is 'tcp' or 'udp'.\n");
|
65
|
+
fprintf(stderr, "\nOption available :\n");
|
66
|
+
fprintf(stderr, " -g ipv4address\n\tforce the gateway to be used as destination for NAT-PMP commands.\n");
|
67
|
+
fprintf(stderr, " -l lifetime\n\tset lifetime for port mapping.\n");
|
68
|
+
fprintf(stderr, " -v\n\tbe verbose.\n");
|
69
|
+
fprintf(stderr, "\n In order to remove a mapping, set it with a lifetime of 0 seconds.\n");
|
70
|
+
fprintf(stderr, " To remove all mappings for your machine, use 0 as private port and lifetime.\n");
|
71
|
+
|
72
|
+
exit(1);
|
73
|
+
}
|
74
|
+
|
75
|
+
#define NO 0
|
76
|
+
#define YES 1
|
77
|
+
|
78
|
+
typedef struct {
|
79
|
+
int protocol;
|
80
|
+
uint16_t privateport;
|
81
|
+
uint16_t publicport;
|
82
|
+
uint32_t lifetime;
|
83
|
+
} port_mapping_t;
|
84
|
+
|
85
|
+
#define MAX_PORT_MAPPINGS 32
|
86
|
+
|
87
|
+
typedef struct {
|
88
|
+
int verbose;
|
89
|
+
int gateway;
|
90
|
+
port_mapping_t port_mappings[MAX_PORT_MAPPINGS];
|
91
|
+
unsigned port_mappings_count;
|
92
|
+
} arguments_t;
|
93
|
+
|
94
|
+
/*
|
95
|
+
* == Argument parsing ========================================================
|
96
|
+
*/
|
97
|
+
|
98
|
+
static void parse_port_mapping(const char* s, port_mapping_t* p_port_mapping) {
|
99
|
+
p_port_mapping->publicport = 0;
|
100
|
+
p_port_mapping->privateport = 0;
|
101
|
+
p_port_mapping->protocol = NATPMP_PROTOCOL_TCP;
|
102
|
+
|
103
|
+
if(0 == strncasecmp(s, "tcp:", 4)) {
|
104
|
+
s += 4;
|
105
|
+
}
|
106
|
+
else if(0 == strncasecmp(s, "udp:", 4)) {
|
107
|
+
p_port_mapping->protocol = NATPMP_PROTOCOL_UDP;
|
108
|
+
s += 4;
|
109
|
+
}
|
110
|
+
|
111
|
+
if(2 == sscanf(s, "%hu:%hu", &p_port_mapping->publicport, &p_port_mapping->privateport)) {
|
112
|
+
return;
|
113
|
+
}
|
114
|
+
|
115
|
+
if(1 == sscanf(s, "%hu", &p_port_mapping->publicport)) {
|
116
|
+
p_port_mapping->privateport = p_port_mapping->publicport;
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
|
120
|
+
fprintf(stderr, "Cannot parse port mapping '%s'\n", s);
|
121
|
+
exit(1);
|
122
|
+
}
|
123
|
+
|
124
|
+
static void parse_args(const char** argv, arguments_t* args) {
|
125
|
+
in_addr_t lifetime = 3600;
|
126
|
+
|
127
|
+
args->verbose = NO;
|
128
|
+
args->gateway = 0;
|
129
|
+
args->port_mappings_count = 0;
|
130
|
+
|
131
|
+
/* argument parsing */
|
132
|
+
while(*++argv) {
|
133
|
+
if(*argv[0] == '-') {
|
134
|
+
switch((*argv)[1]) {
|
135
|
+
case 'g':
|
136
|
+
if(!*++argv) usage();
|
137
|
+
args->gateway = inet_addr(*argv);
|
138
|
+
break;
|
139
|
+
case 'l':
|
140
|
+
if(!*++argv) usage();
|
141
|
+
lifetime = (unsigned)strtoul(*argv, (char **)NULL, 10);
|
142
|
+
break;
|
143
|
+
case 'v':
|
144
|
+
args->verbose = YES;
|
145
|
+
break;
|
146
|
+
default:
|
147
|
+
usage();
|
148
|
+
};
|
149
|
+
continue;
|
150
|
+
}
|
151
|
+
|
152
|
+
if(args->port_mappings_count == MAX_PORT_MAPPINGS) {
|
153
|
+
fprintf(stderr, "Cannot map more than %d ports at once.\n", MAX_PORT_MAPPINGS);
|
154
|
+
exit(1);
|
155
|
+
}
|
156
|
+
|
157
|
+
port_mapping_t* port_mapping = args->port_mappings + args->port_mappings_count;
|
158
|
+
parse_port_mapping(*argv, port_mapping);
|
159
|
+
port_mapping->lifetime = lifetime;
|
160
|
+
args->port_mappings_count++;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
#define MAX_TRIES 6
|
165
|
+
|
166
|
+
/*
|
167
|
+
* == NAT-PMP high level interface ============================================
|
168
|
+
*/
|
169
|
+
|
170
|
+
static int natpmp_init(natpmp_t* natpmp, arguments_t* args)
|
171
|
+
{
|
172
|
+
int r = initnatpmp(natpmp, args->gateway != 0, args->gateway);
|
173
|
+
fprintf(debug, "initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS");
|
174
|
+
if(r < 0) return NO;
|
175
|
+
|
176
|
+
/* log gateway */
|
177
|
+
struct in_addr gateway_in_use;
|
178
|
+
gateway_in_use.s_addr = natpmp->gateway;
|
179
|
+
fprintf(debug, "using NAT-PMP gateway : %s\n", inet_ntoa(gateway_in_use));
|
180
|
+
|
181
|
+
return YES;
|
182
|
+
}
|
183
|
+
|
184
|
+
static void natpmp_close(natpmp_t* natpmp)
|
185
|
+
{
|
186
|
+
int r = closenatpmp(natpmp);
|
187
|
+
fprintf(debug, "closenatpmp() returned %d (%s)\n", r, r==0?"SUCCESS":"FAILED");
|
188
|
+
}
|
189
|
+
|
190
|
+
static natpmpresp_t* natpmp_wait_for_success_response(natpmp_t* natpmp, natpmpresp_t* response) {
|
191
|
+
int remaining_tries = MAX_TRIES;
|
192
|
+
|
193
|
+
while(remaining_tries > 0) {
|
194
|
+
fd_set fds;
|
195
|
+
struct timeval timeout;
|
196
|
+
|
197
|
+
FD_ZERO(&fds);
|
198
|
+
FD_SET(natpmp->s, &fds);
|
199
|
+
getnatpmprequesttimeout(natpmp, &timeout);
|
200
|
+
|
201
|
+
if(0 > select(FD_SETSIZE, &fds, NULL, NULL, &timeout)) {
|
202
|
+
perror("select()");
|
203
|
+
return 0;
|
204
|
+
}
|
205
|
+
|
206
|
+
int r = readnatpmpresponseorretry(natpmp, response);
|
207
|
+
int sav_errno = errno;
|
208
|
+
fprintf(debug, "readnatpmpresponseorretry returned %d (%s)\n", r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED"));
|
209
|
+
if(r == 0) {
|
210
|
+
fprintf(debug, "epoch = %u\n", response->epoch);
|
211
|
+
return response;
|
212
|
+
}
|
213
|
+
|
214
|
+
if(r != NATPMP_TRYAGAIN) {
|
215
|
+
#ifdef ENABLE_STRNATPMPERR
|
216
|
+
fprintf(debug, "readnatpmpresponseorretry() failed : %s\n", strnatpmperr(r));
|
217
|
+
#endif
|
218
|
+
fprintf(debug, " errno=%d '%s'\n", sav_errno, strerror(sav_errno));
|
219
|
+
return 0;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
fprintf(stderr, "Giving up after %d tries.\n", MAX_TRIES);
|
224
|
+
return 0;
|
225
|
+
}
|
226
|
+
|
227
|
+
static const char* natpmp_public_address(natpmp_t* natpmp, char* publicaddress)
|
228
|
+
{
|
229
|
+
int r = sendpublicaddressrequest(natpmp);
|
230
|
+
fprintf(debug, "sendpublicaddressrequest returned %d (%s)\n", r, r==2?"SUCCESS":"FAILED");
|
231
|
+
if(r<0) return 0;
|
232
|
+
|
233
|
+
natpmpresp_t response_buf;
|
234
|
+
natpmpresp_t *response = natpmp_wait_for_success_response(natpmp, &response_buf);
|
235
|
+
if(!response)
|
236
|
+
return 0;
|
237
|
+
|
238
|
+
/* TODO : check that response.type == 0 */
|
239
|
+
fprintf(debug, "Public IP address : %s\n", inet_ntoa(response->pnu.publicaddress.addr));
|
240
|
+
sprintf(publicaddress, "%s", inet_ntoa(response->pnu.publicaddress.addr));
|
241
|
+
|
242
|
+
return publicaddress;
|
243
|
+
}
|
244
|
+
|
245
|
+
static int natpmp_map_port(natpmp_t* natpmp, port_mapping_t* port_mapping, unsigned* lifetime) {
|
246
|
+
int r = sendnewportmappingrequest(natpmp, port_mapping->protocol,
|
247
|
+
port_mapping->privateport, port_mapping->publicport,
|
248
|
+
port_mapping->lifetime);
|
249
|
+
fprintf(debug, "sendnewportmappingrequest returned %d (%s)\n",
|
250
|
+
r, r==12?"SUCCESS":"FAILED");
|
251
|
+
if(r < 0)
|
252
|
+
return NO;
|
253
|
+
|
254
|
+
natpmpresp_t response_buf;
|
255
|
+
natpmpresp_t *response = natpmp_wait_for_success_response(natpmp, &response_buf);
|
256
|
+
if(!response) return NO;
|
257
|
+
|
258
|
+
*lifetime = response->pnu.newportmapping.lifetime;
|
259
|
+
return YES;
|
260
|
+
}
|
261
|
+
|
262
|
+
/*
|
263
|
+
* == main ====================================================================
|
264
|
+
*/
|
265
|
+
|
266
|
+
int main(int argc, const char ** argv)
|
267
|
+
{
|
268
|
+
|
269
|
+
#ifdef WIN32
|
270
|
+
WSADATA wsaData;
|
271
|
+
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
272
|
+
if(nResult != NO_ERROR)
|
273
|
+
{
|
274
|
+
fprintf(stderr, "WSAStartup() failed.\n");
|
275
|
+
return -1;
|
276
|
+
}
|
277
|
+
#endif
|
278
|
+
|
279
|
+
argv0 = argv[0];
|
280
|
+
arguments_t args;
|
281
|
+
|
282
|
+
parse_args(argv, &args);
|
283
|
+
|
284
|
+
debug = args.verbose ? stderr : fopen("/dev/null", "w");
|
285
|
+
|
286
|
+
// if(args.verbose) {
|
287
|
+
// unsigned i = 0;
|
288
|
+
// for(i = 0; i<args.port_mappings_count; ++i) {
|
289
|
+
// port_mapping_t* mapping = args.port_mappings + i;
|
290
|
+
//
|
291
|
+
// const char* protocol = mapping->protocol == NATPMP_PROTOCOL_UDP ? "udp" : "tcp";
|
292
|
+
// fprintf(stderr, "%s: public:%hu -> localhost:%hu: pending (lifetime %u)\n",
|
293
|
+
// protocol, mapping->publicport, mapping->privateport, mapping->lifetime);
|
294
|
+
// }
|
295
|
+
// }
|
296
|
+
|
297
|
+
/*
|
298
|
+
* Try to get NAT-PMP public IP. We use that to decide whether we are
|
299
|
+
* going NAT-PMP or UPnP.
|
300
|
+
*/
|
301
|
+
|
302
|
+
natpmp_t natpmp;
|
303
|
+
|
304
|
+
if(!natpmp_init(&natpmp, &args)) {
|
305
|
+
fprintf(stderr, "Cannot initialize NAT-PMP.\n");
|
306
|
+
return 1;
|
307
|
+
}
|
308
|
+
|
309
|
+
char publicaddress_buf[32];
|
310
|
+
const char* publicaddress = natpmp_public_address(&natpmp, publicaddress_buf);
|
311
|
+
if(!publicaddress) {
|
312
|
+
fprintf(stderr, "NAT-PMP: Cannot find public IP address. NAT-PMP is not available.\n");
|
313
|
+
}
|
314
|
+
|
315
|
+
if(publicaddress) {
|
316
|
+
if(args.port_mappings_count == 0)
|
317
|
+
printf("%s\n", publicaddress);
|
318
|
+
|
319
|
+
unsigned i = 0;
|
320
|
+
for(i = 0; i<args.port_mappings_count; ++i) {
|
321
|
+
port_mapping_t* mapping = args.port_mappings + i;
|
322
|
+
|
323
|
+
unsigned lifetime = 0;
|
324
|
+
int r = natpmp_map_port(&natpmp, mapping, &lifetime);
|
325
|
+
|
326
|
+
const char* protocol = mapping->protocol == NATPMP_PROTOCOL_UDP ? "udp" : "tcp";
|
327
|
+
fprintf(stderr, "NAT-PMP: %s: %s:%hu -> localhost:%hu: %s (lifetime %u)\n",
|
328
|
+
protocol, publicaddress, mapping->publicport, mapping->privateport, (r ? "OK" : "FAIL"), lifetime);
|
329
|
+
|
330
|
+
if(!r) break;
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
natpmp_close(&natpmp);
|
335
|
+
return 0;
|
336
|
+
}
|
337
|
+
|
data/lib/pipe2me/cli-foreman.rb
CHANGED
@@ -3,16 +3,20 @@ class Pipe2me::CLI < Thor
|
|
3
3
|
option :echo, :type => :boolean, :banner => "Also run echo servers"
|
4
4
|
def start
|
5
5
|
handle_global_options
|
6
|
-
|
6
|
+
|
7
7
|
procfile = options[:echo] ? "pipe2me.procfile.echo" : "pipe2me.procfile"
|
8
8
|
|
9
9
|
File.open procfile, "w" do |io|
|
10
10
|
Pipe2me::Tunnel.tunnel_commands.each do |name, cmd|
|
11
11
|
io.write "#{name}: #{cmd}\n"
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
|
+
# Pipe2me::Tunnel.mapping_commands.each do |name, cmd|
|
15
|
+
# io.write "#{name}: #{cmd}\n"
|
16
|
+
# end
|
17
|
+
|
14
18
|
next unless options[:echo]
|
15
|
-
|
19
|
+
|
16
20
|
Pipe2me::Tunnel.echo_commands.each do |name, cmd|
|
17
21
|
io.write "#{name}: #{cmd}\n"
|
18
22
|
end
|
data/lib/pipe2me/cli-monit.rb
CHANGED
@@ -4,32 +4,37 @@ class Pipe2me::CLI < Thor
|
|
4
4
|
option :echo, :type => :boolean, :banner => "Also run echo servers"
|
5
5
|
def monit(*args)
|
6
6
|
handle_global_options
|
7
|
-
|
7
|
+
|
8
8
|
monitrc_file = create_monitrc
|
9
|
-
|
9
|
+
|
10
10
|
UI.warn "Running: monit -c #{monitrc_file} #{args.join(" ")}"
|
11
11
|
Kernel.exec "monit", "-c", monitrc_file, *args
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
desc "monitrc", "Create monitrc file"
|
15
15
|
option :port, :default => 5555, :banner => "control port"
|
16
16
|
option :echo, :type => :boolean, :banner => "Also run echo servers"
|
17
17
|
def monitrc
|
18
18
|
handle_global_options
|
19
|
-
|
19
|
+
|
20
20
|
monitrc_file = create_monitrc
|
21
21
|
Kernel.exec "monit", "-c", monitrc_file, "-t"
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
|
-
|
25
|
+
|
26
|
+
def which!(cmd)
|
27
|
+
path = `which #{cmd}`.chomp
|
28
|
+
raise "Cannot find #{cmd} in your $PATH. Is it installed?" if path == ""
|
29
|
+
path
|
30
|
+
end
|
31
|
+
|
26
32
|
def create_monitrc
|
27
33
|
path = options[:echo] ? "pipe2me.monitrc.echo" : "pipe2me.monitrc"
|
28
34
|
|
29
35
|
# The daemon binary
|
30
|
-
|
31
|
-
|
32
|
-
|
36
|
+
daemon = "#{which! :daemon} -D #{File.expand_path(Dir.getwd)}"
|
37
|
+
|
33
38
|
port = options[:port]
|
34
39
|
|
35
40
|
logfile = File.expand_path "pipe2me.monit.log"
|
@@ -37,22 +42,23 @@ class Pipe2me::CLI < Thor
|
|
37
42
|
FileUtils.mkdir_p piddir
|
38
43
|
|
39
44
|
commands = Pipe2me::Tunnel.tunnel_commands
|
45
|
+
# commands += Pipe2me::Tunnel.mapping_commands
|
40
46
|
commands += Pipe2me::Tunnel.echo_commands if options[:echo]
|
41
|
-
|
47
|
+
|
42
48
|
File.open path, "w", 0600 do |io|
|
43
49
|
require "erb"
|
44
50
|
|
45
51
|
erb = ERB.new MONITRC_ERB
|
46
52
|
io.write erb.result(self.send(:binding))
|
47
53
|
end
|
48
|
-
|
54
|
+
|
49
55
|
UI.success "Created #{path}"
|
50
|
-
|
56
|
+
|
51
57
|
path
|
52
58
|
end
|
53
59
|
|
54
60
|
MONITRC_ERB = %q{
|
55
|
-
set daemon 10
|
61
|
+
set daemon 10
|
56
62
|
set httpd port <%= port %> and use address localhost allow localhost
|
57
63
|
|
58
64
|
<% commands.each do |name, cmd| %>
|
data/lib/pipe2me/cli.rb
CHANGED
@@ -2,12 +2,12 @@ require "thor"
|
|
2
2
|
|
3
3
|
class Pipe2me::CLI < Thor
|
4
4
|
class_option :dir, :type => :string
|
5
|
-
class_option :verbose, :type => :boolean, :aliases =>
|
6
|
-
class_option :quiet, :type => :boolean, :aliases =>
|
5
|
+
class_option :verbose, :type => :boolean, :aliases => "-v"
|
6
|
+
class_option :quiet, :type => :boolean, :aliases => "-q"
|
7
7
|
class_option :silent, :type => :boolean
|
8
|
-
|
8
|
+
|
9
9
|
private
|
10
|
-
|
10
|
+
|
11
11
|
def handle_global_options
|
12
12
|
UI.verbosity = 2
|
13
13
|
if options[:verbose]
|
@@ -25,24 +25,24 @@ class Pipe2me::CLI < Thor
|
|
25
25
|
end
|
26
26
|
|
27
27
|
public
|
28
|
-
|
28
|
+
|
29
29
|
def self.exit_on_failure?; true; end
|
30
|
-
|
30
|
+
|
31
31
|
desc "version", "print version information"
|
32
32
|
def version
|
33
33
|
handle_global_options
|
34
|
-
|
34
|
+
|
35
35
|
puts Pipe2me::VERSION
|
36
36
|
end
|
37
37
|
|
38
38
|
desc "setup", "fetch a new tunnel setup"
|
39
|
-
option :server, :aliases =>
|
39
|
+
option :server, :aliases => "-s", :default => "http://test.pipe2.me"
|
40
40
|
option :token, :required => true # "tunnel token"
|
41
41
|
option :protocols, :default => "https" # "protocol names, e.g. 'http,https,imap'"
|
42
42
|
option :ports, :type => :string # "local ports, one per protocol"
|
43
43
|
def setup
|
44
44
|
handle_global_options
|
45
|
-
|
45
|
+
|
46
46
|
Pipe2me::Config.server = options[:server]
|
47
47
|
server_info = Pipe2me::Tunnel.setup options
|
48
48
|
|
@@ -53,7 +53,7 @@ class Pipe2me::CLI < Thor
|
|
53
53
|
desc "env", "show tunnel configuration"
|
54
54
|
def env(*args)
|
55
55
|
handle_global_options
|
56
|
-
|
56
|
+
|
57
57
|
puts File.read("pipe2me.local.inc")
|
58
58
|
puts File.read("pipe2me.info.inc")
|
59
59
|
end
|
@@ -61,21 +61,21 @@ class Pipe2me::CLI < Thor
|
|
61
61
|
desc "verify", "Verify the tunnel"
|
62
62
|
def verify
|
63
63
|
handle_global_options
|
64
|
-
|
64
|
+
|
65
65
|
Pipe2me::Tunnel.verify
|
66
66
|
end
|
67
67
|
|
68
68
|
desc "update", "Updates configuration"
|
69
69
|
def update
|
70
70
|
handle_global_options
|
71
|
-
|
71
|
+
|
72
72
|
Pipe2me::Tunnel.update
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
desc "check", "check online status"
|
76
76
|
def check
|
77
77
|
handle_global_options
|
78
|
-
|
78
|
+
|
79
79
|
Pipe2me::Tunnel.check
|
80
80
|
end
|
81
81
|
end
|
data/lib/pipe2me/config.rb
CHANGED
data/lib/pipe2me/ext/http.rb
CHANGED
@@ -21,10 +21,10 @@ module Pipe2me::HTTP
|
|
21
21
|
end
|
22
22
|
|
23
23
|
extend Forwardable
|
24
|
-
delegate [ :code, :url ] => :@response
|
24
|
+
delegate [ :code, :url ] => :@response
|
25
25
|
|
26
26
|
def message #:nodoc:
|
27
|
-
"#{url}: #{code} #{@response[0..120]} (#{@response.response.class})"
|
27
|
+
"#{url}: #{code} #{@response[0..120]} (#{@response.response.class})"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
data/lib/pipe2me/ext/sys.rb
CHANGED
@@ -2,14 +2,14 @@ require "shellwords"
|
|
2
2
|
|
3
3
|
module Pipe2me::Sys
|
4
4
|
extend self
|
5
|
-
|
5
|
+
|
6
6
|
class ExitError < RuntimeError; end
|
7
|
-
|
7
|
+
|
8
8
|
def sys(*args)
|
9
9
|
cmd, stdout = _sys(*args)
|
10
10
|
return stdout if $?.exitstatus == 0
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def sys!(*args)
|
14
14
|
cmd, stdout = _sys(*args)
|
15
15
|
return stdout if $?.exitstatus == 0
|
@@ -19,18 +19,18 @@ module Pipe2me::Sys
|
|
19
19
|
def sh(*args)
|
20
20
|
sys "sh", "-c", *args
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def sh!(*args)
|
24
24
|
sys! "sh", "-c", *args
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
private
|
28
|
-
|
28
|
+
|
29
29
|
def _sys(*args)
|
30
30
|
cmd = args.
|
31
31
|
map { |arg| Shellwords.escape arg.to_s }.
|
32
32
|
join(" ")
|
33
|
-
|
33
|
+
|
34
34
|
UI.debug cmd
|
35
35
|
stdout = IO.popen(cmd, &:read)
|
36
36
|
[ cmd, stdout ]
|
@@ -7,7 +7,7 @@ module Pipe2me::Tunnel::Commands
|
|
7
7
|
def tunnels
|
8
8
|
@tunnels ||= begin
|
9
9
|
urls, ports = config.urls, config.ports.to_s.split(",")
|
10
|
-
|
10
|
+
|
11
11
|
urls.zip(ports).map do |url, local_port|
|
12
12
|
uri = URI.parse(url)
|
13
13
|
[ uri.scheme, uri.port, local_port || uri.port ]
|
@@ -16,17 +16,25 @@ module Pipe2me::Tunnel::Commands
|
|
16
16
|
end
|
17
17
|
|
18
18
|
public
|
19
|
-
|
19
|
+
|
20
20
|
# return an arry [ [name, command ], [name, command ], .. ]
|
21
21
|
def tunnel_commands
|
22
22
|
tunnel_uri = URI.parse config.tunnel
|
23
|
-
|
23
|
+
|
24
24
|
tunnels.map do |protocol, remote_port, local_port|
|
25
25
|
next unless cmd = port_tunnel_command(tunnel_uri, protocol, remote_port, local_port)
|
26
26
|
[ "#{protocol}_#{remote_port}", cmd ]
|
27
27
|
end.compact
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
|
+
# def mapping_commands
|
31
|
+
# natpmpc = File.expand_path "#{File.dirname(__FILE__)}/../bin/natpmpc"
|
32
|
+
# mappings = tunnels.map do |_, remote_port, local_port|
|
33
|
+
# "tcp:#{remote_port}:#{local_port}"
|
34
|
+
# end
|
35
|
+
# [ [ "natpmpc", "#{natpmpc} #{mappings.join(" ")} && sleep 10000" ] ]
|
36
|
+
# end
|
37
|
+
|
30
38
|
def echo_commands
|
31
39
|
tunnels.map do |protocol, remote_port, local_port|
|
32
40
|
next unless cmd = echo_server_command(protocol, local_port)
|
@@ -41,10 +49,10 @@ module Pipe2me::Tunnel::Commands
|
|
41
49
|
raise "Cannot find #{cmd} in your $PATH. Is it installed?" if path == ""
|
42
50
|
path
|
43
51
|
end
|
44
|
-
|
52
|
+
|
45
53
|
def port_tunnel_command(tunnel_uri, protocol, remote_port, local_port)
|
46
54
|
autossh = which! :autossh
|
47
|
-
|
55
|
+
|
48
56
|
cmd = <<-SHELL
|
49
57
|
env AUTOSSH_GATETIME=0 # comments work here..
|
50
58
|
#{autossh}
|
@@ -55,12 +63,13 @@ module Pipe2me::Tunnel::Commands
|
|
55
63
|
-i #{T::SSH_PRIVKEY}
|
56
64
|
-o StrictHostKeyChecking=no
|
57
65
|
-o UserKnownHostsFile=pipe2me.known_hosts
|
66
|
+
-o PasswordAuthentication=no
|
58
67
|
-N
|
59
68
|
SHELL
|
60
|
-
|
69
|
+
|
61
70
|
# remove comments and newlines from commands
|
62
71
|
cmd.gsub(/( *#.*|\s+)/, " ").gsub(/(^ )|( $)/, "")
|
63
|
-
end
|
72
|
+
end
|
64
73
|
|
65
74
|
def echo_server_command(protocol, port)
|
66
75
|
binary = File.dirname(__FILE__) + "/echo/#{protocol}"
|
@@ -44,7 +44,7 @@ require "webrick/https"
|
|
44
44
|
|
45
45
|
RACK_SERVER_OPTIONS = {
|
46
46
|
:app => Application,
|
47
|
-
:BindAddress => "localhost",
|
47
|
+
# :BindAddress => "localhost",
|
48
48
|
:Port => ENV["PORT"] || 8080,
|
49
49
|
:server => "webrick",
|
50
50
|
:Logger => WEBrick::BasicLog.new($stderr, WEBrick::BasicLog::WARN)
|
data/lib/pipe2me/tunnel.rb
CHANGED
data/lib/pipe2me/version.rb
CHANGED
data/test/env-test.sh
CHANGED
data/test/monitrc-test.sh
CHANGED
data/test/opensslkey-test.sh
CHANGED
@@ -7,7 +7,7 @@ describe "openssl tests"
|
|
7
7
|
it_sets_up_openssl_certs() {
|
8
8
|
fqdn=$($pipe2me setup --server $pipe2me_server --token $pipe2me_token)
|
9
9
|
test -f pipe2me.openssl.priv
|
10
|
-
cat pipe2me.openssl.priv | grep "BEGIN
|
10
|
+
cat pipe2me.openssl.priv | grep -E "BEGIN.*PRIVATE KEY"
|
11
11
|
|
12
12
|
test -f pipe2me.openssl.cert
|
13
13
|
cat pipe2me.openssl.cert | grep "BEGIN CERTIFICATE"
|
data/test/redirection-test.sh
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env roundup
|
2
|
-
describe 'a HTTP(s) connection to subdomain.$pipe2me_server redirects to subdomain.$pipe2me_server:port'
|
2
|
+
describe 'a HTTP(s) connection to subdomain.$pipe2me_server redirects to subdomain.$pipe2me_server:port'
|
3
3
|
|
4
4
|
. $(dirname $1)/testhelper.inc
|
5
5
|
|
data/test/setup-test.sh
CHANGED
@@ -6,12 +6,14 @@ describe "tunnel setup"
|
|
6
6
|
# setup a tunnel
|
7
7
|
it_sets_up_tunnels() {
|
8
8
|
fqdn=$($pipe2me setup --server $pipe2me_server --token $pipe2me_token --ports 8100,8101 --protocols http,https)
|
9
|
-
|
9
|
+
|
10
|
+
test "$fqdn" != ""
|
11
|
+
|
10
12
|
# pipe2me setup --server $pipe2me_server returns the fqdn of the subdomain and nothing else
|
11
|
-
test 1 -eq $(echo $fqdn | wc -l)
|
13
|
+
test 1 -eq $(echo $fqdn | wc -l)
|
12
14
|
|
13
15
|
# The subdomain is actually a subdomain.
|
14
|
-
echo $fqdn | grep \.pipe2\.
|
16
|
+
echo $fqdn | grep \.pipe2\.
|
15
17
|
|
16
18
|
# Cannot setup a second tunnel in the same directory.
|
17
19
|
! $pipe2me setup --server $pipe2me_server --token $pipe2me_token
|
data/test/sshkey-test.sh
CHANGED
data/test/testhelper.inc
CHANGED
data/test/testhelper.release
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
pipe2me_server=http://pipe2.
|
1
|
+
pipe2me_server=http://test.pipe2.me
|
2
2
|
pipe2me_token=test@pipe2me
|
data/test/verify-test.sh
CHANGED
@@ -8,11 +8,11 @@ it_sets_up_tunnels_and_verifies() {
|
|
8
8
|
fqdn=$($pipe2me setup --server $pipe2me_server --token short@pipe2me)
|
9
9
|
|
10
10
|
# pipe2me setup --server $pipe2me_server returns the fqdn of the subdomain and nothing else
|
11
|
-
test 1 -eq $(echo $fqdn | wc -l)
|
11
|
+
test 1 -eq $(echo $fqdn | wc -l)
|
12
12
|
|
13
13
|
verified=$($pipe2me verify)
|
14
|
-
test "$fqdn"
|
15
|
-
|
14
|
+
test "$fqdn" = "$verified"
|
15
|
+
|
16
16
|
# sleep 4 seconds. The tunnel lives for 3 seconds
|
17
17
|
sleep 4
|
18
18
|
! $pipe2me verify
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pipe2me-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
description: pipe2me command line client V0.2.
|
69
|
+
description: pipe2me command line client V0.2.9; (c) The kinko team, 2013, 2014.
|
70
70
|
email: contact@kinko.me
|
71
71
|
executables:
|
72
72
|
- pipe2me
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- bin/pipe2me
|
78
78
|
- bin/pipe2med
|
79
79
|
- lib/pipe2me.rb
|
80
|
+
- lib/pipe2me/bin/natpmpc
|
80
81
|
- lib/pipe2me/cli-foreman.rb
|
81
82
|
- lib/pipe2me/cli-monit.rb
|
82
83
|
- lib/pipe2me/cli.rb
|
@@ -131,5 +132,5 @@ rubyforge_project:
|
|
131
132
|
rubygems_version: 2.2.1
|
132
133
|
signing_key:
|
133
134
|
specification_version: 4
|
134
|
-
summary: pipe2me command line client V0.2.
|
135
|
+
summary: pipe2me command line client V0.2.9; (c) The kinko team, 2013, 2014.
|
135
136
|
test_files: []
|