336 Commits

Author SHA1 Message Date
idk
7048131842 Add the TLS Configuration to the configuration generator 2021-02-28 16:17:29 -05:00
idk
b47b3971f7 Add the TLS Configuration to the configuration generator 2021-02-28 16:16:30 -05:00
idk
e31a7636d0 tweak TLS configuration options 2021-02-28 16:10:55 -05:00
idk
9b05750814 TLS Certificate generation helper 2021-02-28 15:28:53 -05:00
idk
494f0274ba Add TLS Options 2021-02-28 14:54:48 -05:00
idk
a079a9c9ff Get ready for using a proper template 2021-02-28 14:19:46 -05:00
idk
fa15eeec97 Update default tunnels.ini 2021-02-28 13:39:04 -05:00
idk
d5422aee75 ditch the old interface options that never worked and weren't actually in the best place anyway 2021-02-28 13:20:32 -05:00
idk
4232b6e197 use interface options across all base tunnel types 2021-02-28 13:17:13 -05:00
idk
fcdd8b7f52 Start work on supporting TLS for tunnels, begin by switching all optional args to the interface instead of the concrete type 2021-02-28 12:34:22 -05:00
idk
529a5f77cb fix output of conf.Print 2021-02-05 21:58:30 -05:00
idk
8be5dfbee0 set enough defaults to validate new config 2020-09-20 16:58:04 -04:00
idk
87e663ed3d set enough defaults to validate new config 2020-09-20 16:48:04 -04:00
idk
ff11aeebc4 set enough defaults to validate new config 2020-09-20 16:42:24 -04:00
idk
8e0af0c4f6 add support for the config file 2020-09-19 23:21:56 -04:00
idk
3ab932c170 Fix error in config directory 2020-01-05 13:51:07 -05:00
idk
6159dc47f0 Fix error in config directory 2020-01-05 13:48:30 -05:00
idk
bf6b920eff add go.mod 2019-12-31 21:57:35 -05:00
idk
aa52be69ff remove vendor dir 2019-10-21 13:53:41 -04:00
idk
d2f767dbe0 clean up conditional compilation 2019-09-28 00:10:36 -04:00
idk
b89d62e481 update the manager to include noui 2019-09-27 23:45:37 -04:00
idk
06113918ea update the manager to include noui 2019-09-27 23:31:32 -04:00
idk
a884fa4692 update the manager to include noui 2019-09-27 23:29:17 -04:00
idk
fc36f9cf6f fix go vet for ./interface 2019-09-11 23:18:29 -04:00
idk
3248dd789d fix go vet for ./interface 2019-09-11 23:12:33 -04:00
idk
71ca8cd65f add in http outproxy helpers 2019-09-08 17:01:05 -04:00
idk
60e9f15b18 add in the outproxy helpers 2019-09-08 16:20:30 -04:00
idk
ee8617deb0 fix helpers 2019-09-06 16:43:33 -04:00
idk
029317222e bandwidth limits for TCP 2019-09-05 17:26:04 -04:00
idk
bcd32aa8ad bandwidth limits for TCP 2019-09-05 17:25:46 -04:00
idk
3c1a44e1d2 only limit if bytelimit > 0 2019-09-05 02:08:31 -04:00
idk
7167ba3a1c add per-client bandwidth limiter 2019-09-05 01:54:28 -04:00
idk
3ff494c374 add per-client bandwidth limiter 2019-09-05 01:45:17 -04:00
idk
aebbe18f3b bump version 2019-09-02 20:49:55 -04:00
idk
081b25d54c re-add noui version 2019-09-02 20:46:17 -04:00
idk
78306cc9e6 give more information when saving a key, like the name 2019-09-01 23:48:16 -04:00
idk
0e40939f7d ssure that a config file exists even if null 2019-09-01 21:23:00 -04:00
idk
ccc29b5e66 purge redundant config items! 2019-08-31 16:55:22 -04:00
idk
36655256c3 fix client control panel in webui 2019-08-31 15:12:08 -04:00
idk
efccedaafb next part of the migration to a single standardized config struct 2019-08-31 13:22:32 -04:00
idk
a75baf9db7 next part of the migration to a single standardized config struct 2019-08-31 13:22:12 -04:00
idk
d67c0c0e31 move the helpers 2019-08-31 03:12:54 -04:00
idk
e88e3a0a6b move the helpers 2019-08-31 03:12:09 -04:00
idk
f530ccd37f Fix the helpers 2019-08-31 03:05:50 -04:00
idk
afdc44afc6 Fix the helpers 2019-08-31 03:02:13 -04:00
idk
6b873f4fc2 update the interface 2019-08-31 02:50:11 -04:00
idk
c427d576cb more prep to reduce the amount of repeated configuration code 2019-08-31 00:13:20 -04:00
idk
383fafea25 more prep to reduce the amount of repeated configuration code 2019-08-31 00:13:10 -04:00
idk
9254afc776 move config stuff around 2019-08-25 20:32:50 -04:00
idk
29c48f906c begin config cleanup 2019-08-25 19:21:11 -04:00
idk
38a4e1b3ad begin config cleanup 2019-08-25 19:20:54 -04:00
idk
bd255b651b fix cli tool 2019-08-23 20:04:16 -04:00
idk
7b7238db56 fix cli tool 2019-08-23 20:03:59 -04:00
idk
e0e31c041a vpn prep 2019-08-20 23:53:47 -04:00
idk
a8b416b8b1 update CSS 2019-08-20 19:17:44 -04:00
idk
61b8dc0813 update CSS 2019-08-20 19:14:51 -04:00
idk
862b7a8c3a update CSS 2019-08-20 18:52:54 -04:00
idk
d8755c1229 update CSS 2019-08-20 18:41:14 -04:00
idk
0131d84eb5 fix the webview UI 2019-08-20 17:14:34 -04:00
idk
2643598a6e fix inverted server detection 2019-08-20 15:48:22 -04:00
idk
8bc137072c launch webui 2019-08-20 02:18:02 -04:00
idk
976338c5c9 move gui bits around so I can re-use them better 2019-08-20 01:17:02 -04:00
idk
6274e4ac6b Experimental GTKWebkit based UI 2019-08-19 02:45:09 -04:00
idk
70689f669f add in browserproxy 2019-08-14 19:41:35 -04:00
idk
86a305d47f add in browserproxy 2019-08-14 19:40:47 -04:00
idk
0e126429da gofmt 2019-08-14 19:19:28 -04:00
idk
e459edd194 add in hashhash option 2019-08-14 19:05:58 -04:00
idk
b6c3371366 update modules 2019-08-14 16:47:32 -04:00
idk
7c0d7cb0d5 modules 2019-08-14 16:15:50 -04:00
idk
888fe2e1bb experiment with word-based representation of base32 addresses for human-to-human transmission 2019-08-14 13:21:49 -04:00
idk
eff15e73ba Human-readable sharable hashes 2019-08-14 00:46:35 -04:00
idk
a812fbd784 human-readable hash experiment 2019-08-13 23:23:16 -04:00
idk
a7f81444e2 add CSRF prevention features 2019-07-11 19:31:18 -04:00
idk
a781f8cea1 add CSRF prevention features 2019-07-11 19:22:14 -04:00
idk
d708ea6a18 add CSRF prevention features 2019-07-11 19:21:58 -04:00
idk
a40083695e add CSRF prevention features 2019-07-11 19:21:52 -04:00
idk
03255526ec add CSRF prevention features 2019-07-11 19:21:24 -04:00
idk
2779413484 Add untracked files 2019-06-25 12:34:11 -04:00
idk
593a62f27c fix non-color pages from the handler 2019-06-25 11:41:22 -04:00
idk
c3192414f7 add controller options, the actual function will be determined by the tunnel type 2019-06-14 01:09:55 -04:00
idk
d7607117be udp service stability improvements, prep for kcp-over-i2p tunnels and easy VPN tunnels 2019-06-12 10:31:24 -04:00
idk
22de47a2c5 udp service stability improvements, prep for kcp-over-i2p tunnels and easy VPN tunnels 2019-06-12 10:30:32 -04:00
idk
0cd844cbd8 udp service stability improvements, prep for kcp-over-i2p tunnels and easy VPN tunnels 2019-06-12 09:16:13 -04:00
idk
3c99520aa7 I do have to get keys from the interface 2019-06-09 23:10:29 -04:00
idk
713635d568 try and improve UDP a little 2019-05-29 22:45:04 -04:00
idk
d771ba0ea8 fix UDP port to prioritize java i2p 2019-05-29 12:09:24 -04:00
idk
88a0bd74cb fix retry loop in UDP 2019-05-29 12:03:21 -04:00
idk
f1a9fa0efd update readme 2019-05-25 14:56:37 -04:00
idk
339cafddeb controller updates, stability updates, use stable sam3 2019-05-25 14:46:23 -04:00
idk
9df4822e1e re-generate conpatibility 2019-05-18 16:58:44 -04:00
idk
433aef42fe fix bugs, important interface stuff 2019-05-18 11:24:04 -04:00
idk
76b5f7acb2 start-stop-restart for TCP server 2019-05-18 10:43:57 -04:00
idk
d5f792142e begin web control interface 2019-05-17 19:02:08 -04:00
idk
70a8ab4019 gofmt 2019-05-12 21:37:42 -04:00
idk
5ddea40045 Force initialization of the config memory 2019-05-12 21:37:26 -04:00
idk
7fe45cca93 Fix interrupt handler 2019-05-12 10:52:18 -04:00
idk
4319726630 activate http proxy 2019-05-11 22:37:59 -04:00
idk
00e5cb49c7 making it a web interface 2019-05-11 17:03:01 -04:00
idk
20d1d9f244 setting up for an actual control panel 2019-05-11 15:37:32 -04:00
idk
25556ee378 fix dockerfile 2019-05-11 02:47:08 -04:00
idk
62c065c510 rename daemon 2019-05-11 00:43:46 -04:00
idk
5df5187cc0 update readme, make it possible to go get samcatd 2019-05-11 00:35:43 -04:00
idk
00488deee3 create a web interface 2019-05-11 00:26:54 -04:00
idk
df3c2edac0 create a web interface 2019-05-11 00:26:24 -04:00
idk
c4cbf34ade add in user/password authentication to the new web interface 2019-05-10 15:48:52 -04:00
idk
478d69d105 generic info handlers for SAMTunnel 2019-05-09 23:50:48 -04:00
idk
5a08db5475 generic info handlers for SAMTunnel 2019-05-09 23:49:31 -04:00
idk
29735355fe fix osx travis 2019-04-26 00:51:48 -04:00
idk
ff8389a7c9 enable use of all current options 2019-04-26 00:27:43 -04:00
idk
89b42eb2bf enable new sigs from config files 2019-04-26 00:00:19 -04:00
idk
de9ea2d402 enable new sigs from config files 2019-04-25 23:56:12 -04:00
idk
790f01be80 use sigtypes from conig files 2019-04-25 23:52:08 -04:00
idk
7135facd9c cleanup, add signature type option 2019-04-25 22:58:49 -04:00
idk
7889f63232 don't do the recopy on all fmts 2019-04-20 19:56:27 -04:00
idk
0e51342fe0 Merge branch 'master' of github.com:eyedeekay/sam-forwarder 2019-04-20 19:33:58 -04:00
idk
4a28a7a07d fix make deps target 2019-04-20 19:33:10 -04:00
idk
ec6172e4d1 Merge pull request #4 from eyedeekay/interfaces
Interfaces
2019-04-20 23:12:32 +00:00
idk
5ede568549 switch to using interfaces 2019-04-20 18:02:54 -04:00
idk
ac5f5e3313 switch to tunnel interfaces 2019-04-20 16:29:26 -04:00
idk
fdf75d99a0 add the tcp folder and the backward-compatability files 2019-04-20 16:04:16 -04:00
idk
8b4b86b3ee log even more, force key regeneration when save is not selected 2019-02-09 19:50:47 -05:00
idk
ac76fc7a5c more key stuff. Literally one app is broken but it has to be in here 2019-02-09 18:32:24 -05:00
idk
ffdf5d2299 log key saves 2019-02-09 17:44:23 -05:00
idk
e59b43395f more key management fixes 2019-02-09 17:12:41 -05:00
idk
ac48fd6619 Try and test tunnel key saving and loading 2019-02-09 16:39:50 -05:00
idk
54eb978f11 disable encrypt/decrypt functions for now 2019-02-09 16:22:24 -05:00
idk
afa6a568ff disable encrypt/decrypt functions for now 2019-02-09 16:21:00 -05:00
idk
d7ac6372bf remove irrelevant parts 2019-02-09 15:49:45 -05:00
idk
e3aa6be988 fix path 2019-02-09 15:44:20 -05:00
idk
c291f23435 fix path 2019-02-09 15:43:59 -05:00
idk
bd82f268eb add the stubs for encrypted key files 2019-02-09 15:40:58 -05:00
idk
10d7f7c24a Split up the key stuff to prep for allowing password-based key file encryption as well and be better organized around this part 2019-02-09 14:41:16 -05:00
idk
8f07c65a1f Never use NewKeys by itself, always conditionally 2019-02-09 14:07:39 -05:00
idk
9e7fb0deb6 correct key configuration thing 2019-02-09 13:52:40 -05:00
idk
148ef4096c work on actually improving the save/load keys system 2019-02-09 13:41:53 -05:00
idk
d134080415 I know I have to package the libraries too but I will soon. 2019-01-27 00:35:45 -05:00
idk
aa4a9551f3 Surely transpiling Go to Javascript can't possibly be that simple? 2019-01-26 23:28:24 -05:00
idk
c7a428ed25 Remove some irrelevant parts and add some info to the readme. 2019-01-22 17:15:04 -05:00
idk
04d57c329e calibrate long-test to the slowest laptop I have 2018-12-20 20:40:24 -05:00
idk
246740cb7f only ever run the full test in the docker container. Travis will have to use docker as well. 2018-12-04 12:31:30 -05:00
idk
8882f39efe experiment with setcap 2018-12-04 12:20:27 -05:00
idk
992dc1d464 update readme again, start PACKAGECONF.md 2018-12-04 11:47:48 -05:00
idk
5c13d44e14 start updating Dockerfile and eventually remove crappy version of eephttpd 2018-12-04 11:04:18 -05:00
idk
7808bea943 better example config 2018-12-04 10:55:17 -05:00
idk
c32fb66558 new docs 2018-12-04 10:30:14 -05:00
idk
addfd33936 switch the creation functions 2018-12-03 17:24:52 -05:00
idk
a8093d9e76 more integration of vpn 2018-12-03 17:13:43 -05:00
idk
298df15b2e more integration of vpn 2018-12-03 17:13:36 -05:00
idk
7ae14054a5 more integration of vpn 2018-12-03 17:10:10 -05:00
idk
059eb57d35 more integration of vpn 2018-12-03 16:54:58 -05:00
idk
525d54e7b2 start laying in the VPN thingy 2018-12-03 16:50:50 -05:00
idk
f6aff1be50 I... think that might be a VPN tunnel option. 2018-12-03 13:57:13 -05:00
idk
1112123584 I... think that might be a VPN tunnel option. 2018-12-03 13:53:48 -05:00
idk
fa675eadad improvements to VPN part. 2018-12-03 12:17:02 -05:00
idk
3bc86464f7 improvements to VPN part. 2018-12-03 12:13:06 -05:00
idk
07c87424f5 make webinterface version static 2018-12-02 20:47:48 -05:00
idk
02221ab3a7 update readme, and I'm finally satisified that UDP actually works since I've finally fucking used it, lol. 2018-12-02 12:04:05 -05:00
idk
ce8643b90c mostly UDP fixes, move all the code from kpetku/sam3 to eyedeekay/sam3, move key saving to common 2018-12-02 10:46:51 -05:00
idk
35587dded7 more udp adjustments 2018-12-01 20:22:52 -05:00
idk
fad86f2d42 fix that awful logging in udp 2018-12-01 20:07:52 -05:00
idk
32585c7e2c udp is still broken, but now I'm actually testing it. 2018-12-01 14:40:33 -05:00
idk
c6c4e768aa gofmt 2018-12-01 03:09:03 -05:00
idk
8b288b0332 finally more UDP refinements, but minor. WIP I2P-powered VPN. moving Encrypt/Decrypt keys to own lib, make easier to use soon. 2018-12-01 03:02:41 -05:00
idk
547e1df401 gofmt 2018-11-29 19:49:57 -05:00
idk
cbc735e3d3 fix error with the blacklist thing 2018-11-29 19:36:41 -05:00
idk
5be974dddb fix manager 2018-11-29 19:12:23 -05:00
idk
9a86763243 expose the ini structure 2018-11-29 19:05:19 -05:00
idk
d313a88bc6 optionally write-out configuration file 2018-11-29 19:01:10 -05:00
idk
5d3fd84f4a make ephsite interruptable 2018-11-13 12:41:00 -05:00
idk
23dc60391c make ephsite interruptable 2018-11-13 12:37:30 -05:00
idk
34bee0faf7 add missing libs 2018-11-13 12:31:45 -05:00
idk
292663fae1 added a cleanup function 2018-11-13 03:43:52 -05:00
idk
4baef9026a added a cleanup function 2018-11-13 03:43:41 -05:00
idk
5a33a15207 added a cleanup function 2018-11-13 03:41:28 -05:00
idk
7f05a1c283 Reset when an http connection is closed 2018-10-31 03:12:45 -04:00
idk
c869402fee Reset when an http connection is closed 2018-10-31 03:12:27 -04:00
idk
b8804f758d Reset when an http connection is closed 2018-10-31 03:08:26 -04:00
idk
7e5be05689 nope, it's definitely in colluding_sites_attack. 2018-10-31 02:16:38 -04:00
idk
3ae3641f84 having some issues with http mode. 2018-10-31 02:01:01 -04:00
idk
61f04fd2cb having some issues with http mode. 2018-10-31 01:48:15 -04:00
idk
970d670edf updated readme to reflect recent improvements and additions and current projects. Updated Docs. Current binaries. 2018-09-20 14:30:15 -04:00
idk
930652f52a new clients are better 2018-09-19 19:41:32 -04:00
idk
f7dc34ab34 new clients are better 2018-09-19 19:10:06 -04:00
idk
6b6c74653b web interface stuff 2018-09-19 18:42:09 -04:00
idk
edd8ee3746 better ways of doing client dests 2018-09-19 18:13:37 -04:00
idk
9957f2bc6d simplified clients 2018-09-19 18:01:08 -04:00
idk
2d3a3caf9d add dests to client searches 2018-09-19 17:30:15 -04:00
idk
8bab575a71 add dests to client searches 2018-09-19 17:29:52 -04:00
idk
5a27ae3ff1 add dests to client searches 2018-09-19 17:23:32 -04:00
idk
c75801db46 Better default configuration 2018-09-19 15:46:36 -04:00
idk
7bb6d863ff Better default configuration 2018-09-19 15:39:03 -04:00
idk
23c173ea95 gofmt 2018-09-19 14:53:35 -04:00
idk
18b170a949 improved some UDP stuff I had missed. 2018-09-19 14:52:30 -04:00
idk
e47a8eb94c improved some UDP stuff I had missed. 2018-09-19 14:50:22 -04:00
idk
20e49356c6 improved manager tests 2018-09-19 12:19:11 -04:00
idk
3631c87bfa enabled setting client destinations from ini file. 2018-09-19 12:08:20 -04:00
idk
577a84adf3 made a whole bunch of crap work better. 2018-09-19 11:26:47 -04:00
idk
6e887f10e6 config shouln't even need to be nil. 2018-09-19 11:20:32 -04:00
idk
6f166d6cdd fixed nil checks in tunconf 2018-09-19 11:13:47 -04:00
idk
c0d3bcb238 nope. 2018-09-19 11:09:56 -04:00
idk
38d1564eb0 Removed unnecessary check on tunnel type with new default. 2018-09-19 11:08:38 -04:00
idk
e30ca92b85 gofmt 2018-09-19 10:37:59 -04:00
idk
8ec3f58993 fixed tunconf thing made test more visible 2018-09-19 10:34:29 -04:00
idk
c3fb2e04f3 fixed tunconf thing made test more visible 2018-09-19 10:33:54 -04:00
idk
3e053eeecf more config file refinements 2018-09-19 10:12:03 -04:00
idk
d3881d9cc2 more config file refinements 2018-09-19 10:08:06 -04:00
idk
15f032e310 more config file refinements 2018-09-19 09:49:48 -04:00
idk
4e6d25705f more config file refinements 2018-09-19 09:40:28 -04:00
idk
67d53a6052 removed fail-on-missing config condition 2018-09-19 09:27:28 -04:00
idk
5cb1e29489 more ini pointer refinements 2018-09-19 00:20:49 -04:00
idk
6536f34c23 more ini pointer refinements 2018-09-19 00:05:48 -04:00
idk
c7e2ce21f2 more ini pointer refinements 2018-09-19 00:00:22 -04:00
idk
692de44793 more ini pointer refinements 2018-09-18 23:34:35 -04:00
idk
6e03eba5a4 more ini pointer refinements 2018-09-18 23:33:18 -04:00
idk
4e7a98ee47 more ini pointer refinements 2018-09-18 23:25:23 -04:00
idk
1f4bd09b1c more ini pointer refinements 2018-09-18 23:24:48 -04:00
idk
1b8aef71f5 more ini pointer refinements 2018-09-18 23:15:38 -04:00
idk
02ff8d6b87 fix tunconf error when not passing a config file 2018-09-18 22:58:55 -04:00
idk
b2e016e059 gofmt 2018-09-18 19:31:53 -04:00
idk
9608c7be09 gofmt 2018-09-18 19:16:44 -04:00
idk
acd4f17536 added type tags to search terms. 2018-09-18 19:12:03 -04:00
idk
e031f4483c debug print and search stuff 2018-09-18 18:25:18 -04:00
idk
82814f8dcf debug print and search stuff 2018-09-18 18:05:53 -04:00
idk
68986f6194 added print and search stuff 2018-09-18 17:41:53 -04:00
idk
86c7624075 added print and search stuff 2018-09-18 17:33:58 -04:00
idk
6701d35daf gofmt 2018-09-18 01:42:34 -04:00
idk
f0070524c1 more docs ephemera 2018-09-18 01:27:11 -04:00
idk
a29f56e8c3 Fixed the key thing again. 2018-09-18 01:05:21 -04:00
idk
921289fd4d docs folder. 2018-09-18 00:56:44 -04:00
idk
c016ffa6dc docs folder. 2018-09-18 00:53:03 -04:00
idk
d87c57672e docs folder. 2018-09-18 00:50:45 -04:00
idk
3c415e114a update docs 2018-09-18 00:47:51 -04:00
idk
c2bf0bd822 fix key error 2018-09-18 00:38:08 -04:00
idk
0db741aa00 fixed some names 2018-09-18 00:25:34 -04:00
idk
2b7f275f50 fixed some names 2018-09-18 00:23:30 -04:00
idk
9ab4d5efee fixed some names 2018-09-18 00:14:45 -04:00
idk
364a35c10a fixed some names 2018-09-17 23:46:59 -04:00
idk
3979d87390 added experimental support for encrypted saves 2018-09-17 23:40:09 -04:00
idk
6bc7558bef final tweak to daemon docs. I'll clean up the comments tomorrow night. 2018-09-14 01:34:33 -04:00
idk
db94225e60 link checklist to readme 2018-09-14 01:18:20 -04:00
idk
9bf8bbb7b8 update docs 2018-09-14 01:08:45 -04:00
idk
d1385398d3 update docs, add streaming library to checklist 2018-09-14 01:02:47 -04:00
idk
0d2835d74e update docs, add streaming library to checklist 2018-09-14 00:53:43 -04:00
idk
a013524011 update docs 2018-09-14 00:35:13 -04:00
idk
815e124555 prep to update docs 2018-09-14 00:23:55 -04:00
idk
febf285738 encrypted leasesets are go, but I'm going to take advantage of some oppourtunities re my approach to this project. 2018-09-14 00:23:10 -04:00
idk
3ca55982ec message reliability things. 2018-09-14 00:16:22 -04:00
idk
8f0ce23667 a whole bunch of encrypted leaseset stuff. 2018-09-13 23:31:18 -04:00
idk
58771aa31e a whole bunch of encrypted leaseset stuff. 2018-09-13 23:30:54 -04:00
idk
a3f47f1fed a whole bunch of encrypted leaseset stuff. 2018-09-13 23:30:13 -04:00
idk
6c044b2029 added remaining encrypted leaseset options to tunconf. 2018-09-13 22:13:44 -04:00
idk
1f8c617eb5 updated checklist, fixed minor flaws in checklist 2018-09-13 21:29:07 -04:00
idk
7a05f9e343 added fastrecieve options to tunconf 2018-09-13 21:20:18 -04:00
idk
30f2dbfddf created checklist for implementing the i2cp and tunnel options. 2018-09-13 20:15:42 -04:00
idk
1c455ee84a started a checklist for i2cp options. 2018-09-13 20:01:57 -04:00
idk
569d5efcc3 snip tunconf into reasonable chunks. 2018-09-13 18:19:19 -04:00
idk
92f961bd79 snip tunconf into reasonable chunks. 2018-09-13 18:14:31 -04:00
idk
124b22e986 snip tunconf into reasonable chunks. 2018-09-13 18:14:22 -04:00
idk
fe92d3c89e Shorter flags for samcatd 2018-09-13 17:30:37 -04:00
idk
4ba85e54c1 update usage 2018-09-12 23:58:25 -04:00
idk
4b88902fb1 updated example config file for samcatd 2018-09-12 23:13:11 -04:00
idk
5e51cc87ff Instead I'm just going to have it assume it's a server now. 2018-09-12 23:00:08 -04:00
idk
8c16480db3 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:51:42 -04:00
idk
74b1c390ae Instead I'm just going to have it assume it's a server now. 2018-09-12 22:47:37 -04:00
idk
4ef9263111 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:47:12 -04:00
idk
11c3bb47a6 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:44:55 -04:00
idk
b6a2b334dd Instead I'm just going to have it assume it's a server now. 2018-09-12 22:41:39 -04:00
idk
93ad5b3a43 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:41:15 -04:00
idk
f0bbea5e6d Instead I'm just going to have it assume it's a server now. 2018-09-12 22:33:19 -04:00
idk
9fae6cf923 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:11:30 -04:00
idk
2fd6131127 Instead I'm just going to have it assume it's a server now. 2018-09-12 22:01:56 -04:00
idk
0f283bc8dd Instead I'm just going to have it assume it's a server now. 2018-09-12 21:53:35 -04:00
idk
79ffc5099e Somehow these aren't being appended for some reason. 2018-09-12 21:37:50 -04:00
idk
69009fcfd4 Somehow these aren't being appended for some reason. 2018-09-12 21:36:57 -04:00
idk
81721c166a Somehow these aren't being appended for some reason. 2018-09-12 21:22:33 -04:00
idk
ad27955dfb added a bit of logging 2018-09-12 21:09:21 -04:00
idk
dc48d03118 added a bit of logging 2018-09-12 21:01:57 -04:00
idk
a7ab90b328 added a bit of logging 2018-09-12 20:53:17 -04:00
idk
df9c44b82f added a bit of logging 2018-09-12 20:52:02 -04:00
idk
0aefc3a0e4 added a bit of logging 2018-09-12 20:46:24 -04:00
idk
9d2dcb1749 loop? 2018-09-12 20:35:25 -04:00
idk
f431e8c59b fix make all 2018-09-12 20:28:35 -04:00
idk
2f172136ce manager stuff for clients. 2018-09-12 20:19:11 -04:00
idk
330f5bf0c0 manager stuff for clients. 2018-09-12 20:12:47 -04:00
idk
7c53bd8f3b manager stuff for clients.. 2018-09-12 20:11:31 -04:00
idk
a831dc0c1c manager stuff for clients.. 2018-09-12 20:09:08 -04:00
idk
3fa0b71fc6 manager stuff. 2018-09-12 19:54:21 -04:00
idk
dbd9acb623 manager stuff. 2018-09-12 19:49:14 -04:00
idk
ad6df28bf5 manager stuff. 2018-09-12 19:44:05 -04:00
idk
b93ce475a4 more manager stuff. 2018-09-12 18:36:40 -04:00
idk
3e4780795e extend tunconf a bit more. 2018-09-12 18:23:18 -04:00
idk
cd458b3d1b more tunconf improvements related to the daemon 2018-09-12 18:00:24 -04:00
idk
c3a2f88796 fix typo 2018-09-12 16:59:34 -04:00
idk
b34078bfd1 more manager stuff, readme changes. 2018-09-12 16:52:50 -04:00
idk
e9bc78e215 more work on manager 2018-09-12 16:34:45 -04:00
idk
5b33d09b0c started working on a new daemon for managing multiple tunnels 2018-09-12 16:15:24 -04:00
idk
ee65a82cc9 more improvements to tunconf 2018-09-12 14:35:59 -04:00
idk
237c0ec41e Enabled labels in tunconf. It can be used with or without a top-level label. 2018-09-12 13:43:18 -04:00
idk
1684b4f919 Enabled labels in tunconf. It can be used with or without a top-level label. 2018-09-12 12:52:44 -04:00
idk
55a8568e8c started manager. Needs to finish tunconf. 2018-09-11 23:59:03 -04:00
idk
7e3487ec28 fix docker stuff 2018-09-11 19:12:13 -04:00
idk
96fcfe8a62 am in the wrong tree. 2018-09-11 18:46:22 -04:00
idk
c6ddebedcb I 2018-09-11 18:29:59 -04:00
idk
c1427c74f3 reconcile closers for server and http mode 2018-09-11 15:05:07 -04:00
idk
911f205d6c reconcile closers for server and http mode 2018-09-11 09:29:04 -04:00
idk
d6d12b7ae0 direct people to the better eephttpd 2018-09-11 00:59:25 -04:00
idk
d246d1ba7d update documentation again. 2018-09-10 22:00:49 -04:00
idk
055df02607 finally worked that all out. new binaries. 2018-09-10 21:44:31 -04:00
idk
a945eeeeb7 See if I can keep this from racing. 2018-09-10 21:33:09 -04:00
idk
8630d5fcdd See if I can keep this from racing. 2018-09-10 21:32:55 -04:00
idk
cd3733d2b0 See if I can keep this from racing. 2018-09-10 21:30:45 -04:00
idk
2070ca935a See if I can keep this from racing. 2018-09-10 21:20:09 -04:00
idk
f5d93be0f4 See if I can keep this from racing. 2018-09-10 21:00:09 -04:00
idk
2bd4243384 See if I can keep this from racing. 2018-09-10 20:51:04 -04:00
idk
2336bdbd0b See if I can keep this from racing. 2018-09-10 20:48:53 -04:00
idk
a21f10558d See if I can keep this from racing. 2018-09-10 20:47:58 -04:00
idk
b562d2ba2b See if I can keep this from racing. 2018-09-10 20:33:54 -04:00
idk
b53e0dee95 Figure out where I need to defer those closes. 2018-09-10 20:06:09 -04:00
idk
a874659167 Figure out where I need to defer those closes. 2018-09-10 20:01:40 -04:00
idk
62e18862d8 try it this way instead... 2018-09-10 19:57:20 -04:00
idk
b4d0c2d98f try it this way instead... 2018-09-10 19:56:04 -04:00
idk
7284e84554 Fix crash maybe? 2018-09-10 19:43:38 -04:00
idk
126067d003 more uniformity for http mode 2018-09-10 19:33:59 -04:00
idk
5176224668 more uniformity for http mode 2018-09-10 19:32:53 -04:00
idk
29cc1dc5de better tcp-http bridge 2018-09-10 19:03:40 -04:00
idk
fd96ce4794 fix log thing. 2018-09-10 18:52:31 -04:00
idk
5524660b0c pass the request to the response reader. 2018-09-10 18:36:52 -04:00
idk
bd4201e955 Response writes new headers now too. 2018-09-10 18:16:39 -04:00
idk
8d618e67e2 Response writes new headers now too. 2018-09-10 18:16:09 -04:00
idk
a423c181ca Response writes new headers now too. 2018-09-10 18:14:06 -04:00
idk
848150a4cf Response writes new headers now too. 2018-09-10 18:07:56 -04:00
idk
67055ab95b Response writes new headers now too. 2018-09-10 18:07:42 -04:00
idk
9a9e27272b log a bit more 2018-09-10 17:43:30 -04:00
idk
abc874b6b8 re-generate documentation and stuff 2018-09-10 17:27:34 -04:00
idk
93ddb65858 Merge pull request #3 from eyedeekay/http-mode
Http mode
2018-09-10 17:16:43 -04:00
idk
5e5e79db86 Merge pull request #1 from eyedeekay/http-mode
Http mode
2018-09-10 16:13:04 -04:00
114 changed files with 28208 additions and 4504 deletions

4
.gitignore vendored
View File

@@ -3,3 +3,7 @@ bin/*
.go
*.i2pkeys
*/*.i2pkeys
README.md.asc
samcatd
*/*.pem
*.pem

View File

@@ -21,7 +21,7 @@ before_install:
install:
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
sleep 10;
make deps noopts; else
make deps all; else
sudo service i2pd start; sleep 10;
make deps noopts test;
make deps all test;
sudo service i2pd stop; fi

View File

@@ -1,20 +1,18 @@
FROM alpine:3.8
ARG user=eephttpd
ARG path=example/path
FROM alpine:edge
ARG user=samcatd
ENV samhost=sam-host
ENV samport=7656
ENV args="-r"
ENV args=""
ENV user=$user
ENV GOPATH=/usr
RUN apk update -U
RUN apk add go git make musl-dev
RUN apk add go git make musl-dev webkit2gtk-dev gtk+3.0-dev
RUN mkdir -p /opt/$user
RUN adduser -h /opt/$user -D -g "$user,,,," $user
COPY . /usr/src/eephttpd
WORKDIR /usr/src/eephttpd
RUN make deps server
RUN install -m755 bin/eephttpd /usr/bin/eephttpd
COPY . /usr/src/sam-forwarder
WORKDIR /usr/src/github.com/eyedeekay/sam-forwarder
RUN go get -u github.com/eyedeekay/sam-forwarder/samcatd
RUN make dylink install
USER $user
WORKDIR /opt/$user/
COPY $path /opt/$user/www
CMD eephttpd -f /usr/src/eephttpd/etc/eephttpd/eephttpd.conf -s /opt/$user/ -sh=$samhost -sp=$samport $args
CMD samcatd -f /usr/src/eephttpd/etc/samcatd/tunnels.ini -littleboss start

View File

@@ -1,16 +0,0 @@
Embedding i2p support in your Go application with samforwarder
==============================================================
One neat thing you can do with samforwarder is make eepWeb(?) services configure
themselves automatically by adding it to an existing Go application. To help
with this process, the samforwarder/config/ file has a bunch of helper
functions and a class for parsing configuration files directly. You can import
it, add a few flags(or however you configure your service) and fire off the
forwarder as a goroutne, all you have to do is configure it to forward the port
used by your service. This makes it extremely easy to do, but in my opinion, it
should only be used in this way for applications that would already be safe to
host as services in i2p or other overlay networks. That means avoiding the risk
of out-of-band communication accidentally, such as by making the server retrieve
a resource from a clearnet service.
When I'm less tired and more interested, I'll try to finish this document.

View File

@@ -1,7 +1,18 @@
Copyright 2018 eyedeekay <eyedeekay@safe-mail.net>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

342
Makefile
View File

@@ -1,173 +1,251 @@
GOPATH = $(PWD)/.go
#GOPATH=$(HOME)/go
appname = ephsite
eephttpd = eephttpd
network = si
packagename = sam-forwarder
samcatd = samcatd
network = host
samhost = sam-host
samport = 7656
args = -r
USER_GH=eyedeekay
PREFIX := /
VAR := var/
RUN := run/
LIB := lib/
LOG := log/
ETC := etc/
USR := usr/
LOCAL := local/
VERSION := 0.32.09
GO111MODULE=on
echo:
@echo "$(GOPATH)"
find . -name "*.go" -exec gofmt -w {} \;
find . -name "*.i2pkeys" -exec rm {} \;
find . -path ./.go -prune -o -name "*.go" -exec gofmt -w {} \;
find . -path ./.go -prune -o -name "*.i2pkeys" -exec rm {} \;
find . -path ./.go -prune -o -name "*.pem" -exec rm {} \;
find . -path ./.go -prune -o -name "*.go" -exec cat {} \; | nl
test:
go test
cd udp && go test
cd config && go test
tag:
gothub release -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(packagename) -t v$(VERSION) -d "I2P Tunnel Management tool for Go applications"
recopy:
#find ./tcp/ -name '*.go' -exec cp -rv {} . \;
#sed -i '1s|^|//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future\n|' *.go
## TODO: Remove this, replace with something right
fix-debian:
find ./debian -type f -exec sed -i 's|lair repo key|eyedeekay|g' {} \;
find ./debian -type f -exec sed -i 's|eyedeekay@safe-mail.net|hankhill19580@gmail.com|g' {} \;
try:
./bin/samcatd -f etc/samcatd/tunnels.ini
test: test-keys test-ntcp test-ssu test-config test-manager
long-test: test-serve test
full-test: test test-serve
test-serve:
cd serve_test && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-ntcp:
cd tcp && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-ssu:
cd udp && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-config:
cd config && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-manager:
cd manager && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-keys:
cd i2pkeys && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
refresh:
deps:
go get -u github.com/zieckey/goini
go get -u github.com/eyedeekay/sam-forwarder
go get -u github.com/eyedeekay/sam-forwarder/udp
go get -u github.com/eyedeekay/sam-forwarder/config
go get -u github.com/kpetku/sam3
go get -u github.com/eyedeekay/sam3
build: clean bin/$(appname)
bin/$(appname):
mkdir -p bin
cd main && go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o ../bin/$(appname)
server: clean-server bin/$(eephttpd)
bin/$(eephttpd):
mkdir -p bin
go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o ./bin/$(eephttpd) ./example/serve.go
all: build server
clean-all: clean clean-server
clean:
rm -f bin/$(appname)
clean-server:
rm -f bin/$(eephttpd)
noopts: clean
mkdir -p bin
cd main && go build -o ../bin/$(appname)
go get -u -d github.com/eyedeekay/sam-forwarder/samcatd
install:
install -m755 bin/ephsite /usr/local/bin/ephsite
install -m755 ./bin/$(samcatd) $(PREFIX)$(USR)$(LOCAL)/bin/
install -m644 ./etc/init.d/samcatd $(PREFIX)$(ETC)/init.d
mkdir -p $(PREFIX)$(ETC)/samcatd/ $(PREFIX)$(ETC)/sam-forwarder/ $(PREFIX)$(ETC)/i2pvpn/
install -m644 ./etc/samcatd/tunnels.ini $(PREFIX)$(ETC)/samcatd/
install -m644 ./etc/sam-forwarder/tunnels.ini $(PREFIX)$(ETC)/sam-forwarder/
install-server:
install -m755 bin/eephttpd /usr/local/bin/eephttpd
daemon: clean-daemon bin/$(samcatd)
install-all: install install-server
daemon-webview: bin/$(samcatd)-webview
remove:
daemon-cli: bin/$(samcatd)-cli
gendoc: all
@echo "$(appname) - Easy forwarding of local services to i2p" > USAGE.md
bin/$(samcatd)-cli:
mkdir -p bin
cd samcatd && go build -a -tags "netgo cli" \
-ldflags '-w -extldflags "-static"' \
-o ../bin/$(samcatd)-cli \
./*.go
bin/$(samcatd):
mkdir -p bin
cd samcatd && go build -a -tags "netgo static" \
-ldflags '-w -extldflags "-static"' \
-o ../bin/$(samcatd) \
./*.go
bin/$(samcatd)-webview:
mkdir -p bin
cd samcatd && go build -a -tags "netgo nostatic" \
-o ../bin/$(samcatd)-webview \
./*.go
update:
git config --global url."git@github.com:RTradeLtd".insteadOf "https://github.com/RTradeLtd"
all: daemon-cli daemon daemon-webview
clean: clean-all echo
clean-all: clean-daemon
clean-daemon:
rm -f bin/$(samcatd)*
install-forwarder:
install -m755 bin/$(samcatd) /usr/local/bin/$(samcatd)
install-all: install
gendoc:
@echo "$(samcatd) - Router-independent tunnel management for i2p" > USAGE.md
@echo "=========================================================" >> USAGE.md
@echo "" >> USAGE.md
@echo "$(samcatd) is a daemon which runs a group of forwarding proxies to" >> USAGE.md
@echo "provide services over i2p independent of the router. It also serves" >> USAGE.md
@echo "as a generalized i2p networking utility for power-users. It's" >> USAGE.md
@echo "intended to be a Swiss-army knife for the SAM API." >> USAGE.md
@echo "" >> USAGE.md
@echo "usage:" >> USAGE.md
@echo "------" >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
./bin/$(samcatd) -h 2>> USAGE.md; true
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
make key-management
make example-config
key-management:
@echo "managing $(samcatd) save-encryption keys" >> USAGE.md
@echo "=====================================" >> USAGE.md
@echo "" >> USAGE.md
@echo "In order to keep from saving the .i2pkeys files in plaintext format, samcatd" >> USAGE.md
@echo "can optionally generate a key and encrypt the .i2pkeys files securely. Of" >> USAGE.md
@echo "course, to fully benefit from this arrangement, you need to move those keys" >> USAGE.md
@echo "away from the machine where the tunnel keys(the .i2pkeys file) are located," >> USAGE.md
@echo "or protect them in some other way(sandboxing, etc). If you want to use" >> USAGE.md
@echo "encrypted .i2pkeys files, you can specify a key file to use with the -cr" >> USAGE.md
@echo "option on the terminal or with keyfile option in the .ini file." >> USAGE.md
@echo "" >> USAGE.md
example-config:
@echo "example config - valid for both ephsite and samcat" >> USAGE.md
@echo "==================================================" >> USAGE.md
@echo "" >> USAGE.md
@echo "$(appname) is a forwarding proxy designed to configure a tunnel for use" >> USAGE.md
@echo "with i2p. It can be used to easily forward a local service to the" >> USAGE.md
@echo "i2p network using i2p's SAM API instead of the tunnel interface." >> USAGE.md
@echo "Options are still being added, pretty much as fast as I can put them" >> USAGE.md
@echo "in. For up-to-the-minute options, see [the checklist](config/CHECKLIST.md)" >> USAGE.md
@echo "" >> USAGE.md
@echo "usage:" >> USAGE.md
@echo "------" >> USAGE.md
@echo "(**ephsite** will only use top-level options, but they can be labeled or" >> USAGE.md
@echo "unlabeled)" >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
./bin/$(appname) -h 2>> USAGE.md; true
@echo "(**samcatd** treats the first set of options it sees as the default, and" >> USAGE.md
@echo "does not start tunnels based on unlabeled options unless passed the" >> USAGE.md
@echo "-s flag.)" >> USAGE.md
@echo "" >> USAGE.md
@echo '``` ini' >> USAGE.md
cat etc/samcatd/tunnels.ini >> USAGE.md
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
@echo "$(eephttpd) - Static file server automatically forwarded to i2p" >> USAGE.md
@echo "============================================================" >> USAGE.md
@echo "" >> USAGE.md
@echo "usage:" >> USAGE.md
@echo "------" >> USAGE.md
@echo "" >> USAGE.md
@echo "$(eephttpd) is a static http server which automatically runs on i2p with" >> USAGE.md
@echo "the help of the SAM bridge. By default it will only be available from" >> USAGE.md
@echo "the localhost and it's i2p tunnel. It can be masked from the localhost" >> USAGE.md
@echo "using a container." >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
./bin/$(eephttpd) -h 2>> USAGE.md; true
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
make docker-cmd
@echo "" >> USAGE.md
@echo "instance" >> USAGE.md
@echo "--------" >> USAGE.md
@echo "" >> USAGE.md
@echo "a running instance of eephttpd with the example index file is availble on" >> USAGE.md
@grep 'and on' eephttpd.log | sed 's|and on||g' | tr -d '\t' >> USAGE.md
@echo "" >> USAGE.md
@cat USAGE.md
mv USAGE.md docs/USAGE.md
docker-build:
docker build --force-rm \
--build-arg user=$(eephttpd) \
--build-arg path=example/www \
docker build --build-arg user=$(samcatd) \
-f Dockerfile \
-t eyedeekay/$(eephttpd) .
-t eyedeekay/$(samcatd) .
docker-volume:
docker run -i -t -d \
--name $(eephttpd)-volume \
--volume $(eephttpd):/home/$(eephttpd)/ \
eyedeekay/$(eephttpd); true
docker stop $(eephttpd)-volume; true
docker-run: docker-volume
docker rm -f eephttpd; true
docker-run:
docker rm -f $(samcatd); true
docker run -i -t -d \
--cap-add "net_bind_service" \
--network $(network) \
--env samhost=$(samhost) \
--env samport=$(samport) \
--env args=$(args) \
--network-alias $(eephttpd) \
--hostname $(eephttpd) \
--name $(eephttpd) \
--hostname $(samcatd) \
--name $(samcatd) \
--restart always \
--volumes-from $(eephttpd)-volume \
eyedeekay/$(eephttpd)
-p 127.0.0.1:7957:7957 \
eyedeekay/$(samcatd)
make follow
follow:
docker logs -f $(eephttpd)
docker logs -f $(samcatd)
docker: docker-build docker-volume docker-run
docker-cmd:
@echo "### build in docker" >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
@echo "docker build --build-arg user=$(eephttpd) --build-arg path=example/www -f Dockerfile -t eyedeekay/$(eephttpd) ." >> USAGE.md
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
@echo "### Run in docker" >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
@echo "docker run -i -t -d \\" >> USAGE.md
@echo " --name $(eephttpd)-volume \\" >> USAGE.md
@echo " --volume $(eephttpd):/home/$(eephttpd)/ \\" >> USAGE.md
@echo " eyedeekay/$(eephttpd)" >> USAGE.md
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
@echo "docker run -i -t -d \\" >> USAGE.md
@echo " --network $(network) \\" >> USAGE.md
@echo " --env samhost=$(samhost) \\" >> USAGE.md
@echo " --env samport=$(samport) \\" >> USAGE.md
@echo " --env args=$(args) # Additional arguments to pass to eephttpd\\" >> USAGE.md
@echo " --network-alias $(eephttpd) \\" >> USAGE.md
@echo " --hostname $(eephttpd) \\" >> USAGE.md
@echo " --name $(eephttpd) \\" >> USAGE.md
@echo " --restart always \\" >> USAGE.md
@echo " --volumes-from $(eephttpd)-volume \\" >> USAGE.md
@echo " eyedeekay/$(eephttpd)" >> USAGE.md
@echo '```' >> USAGE.md
docker: docker-build docker-run
index:
pandoc USAGE.md -o example/www/index.html
pandoc README.md -o docs/index.html
pandoc docs/USAGE.md -o example/www/index.html && cp example/www/index.html docs/usage.html
pandoc docs/EMBEDDING.md -o docs/embedding.html
pandoc docs/PACKAGECONF.md -o docs/packageconf.html
pandoc interface/README.md -o docs/interface.html
cp config/CHECKLIST.md docs/config
pandoc docs/config/CHECKLIST.md -o docs/checklist.html
visit:
http_proxy=http://127.0.0.1:44443 surf http://566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzuq.b32.i2p
http_proxy=http://127.0.0.1:4444 surf http://566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzuq.b32.i2p
gojs:
go get -u github.com/gopherjs/gopherjs
GOPHERJS=$(GOPATH)/bin/gopherjs
js:
mkdir -p bin
$(GOPHERJS) build -v --tags netgo \
-o ./javascript/$(samcatd).js \
./samcatd/*.go
cleantar:
rm -f ../$(packagename)_$(VERSION).orig.tar.xz
tar:
tar --exclude .git \
--exclude .go \
--exclude bin \
-cJvf ../$(packagename)_$(VERSION).orig.tar.xz .
sed:
sed -i 's|func(\*Conf)|func(samtunnel.SAMTunnel)|g' ./config/*.go
sed -i 's|func(c \*Conf)|func(c samtunnel.SAMTunnel)|g' ./config/*.go
tasks:
golint ./tcp
#golint ./udp
#golint ./config
#golint ./config
#golint ./config
#golint ./config

205
README.md
View File

@@ -1,9 +1,14 @@
# sam-forwarder
Forward a local port to i2p over the SAM API, or proxy a destination to a port
on the local host. This is a work-in-progress, but the basic functionality is,
there and it's already pretty useful. Everything TCP works, but UDP forwarding
is still not well tested, and UDP clients aren't enabled yet. I'm out of excuses
not to finish it now, too.
on the local host. This is no longer substantially a work-in-progress, it's a
very useful way of configuring applications in an i2ptunnel-like way. TCP and
UDP are supported, but there may be some lingering bugs in UDP, please report
them if found.
## getting
go get -u github.com/eyedeekay/sam-forwarder/samcatd
## building
@@ -15,162 +20,88 @@ and it will be in the folder ./bin/
[![Build Status](https://travis-ci.org/eyedeekay/sam-forwarder.svg?branch=master)](https://travis-ci.org/eyedeekay/sam-forwarder)
## usage
## Usage:
./bin/ephsite -host=host -port=port
There are a number of ways to use sam-forwarder:
So, to serve an eepSite version of a local service on port 8080 -
### [usage/configuration](docs/USAGE.md) as an application(Start here for samcatd)
./bin/ephsite -host=127.0.0.1 -port=8080
### [embedding](docs/EMBEDDING.md) in other applications
For more information, [look here](USAGE.md)
### [encapsulate](docs/PACKAGECONF.md) configuration for i2p-enabled packages
## ini-like configuration
### [implement](interface/README.md) the interface for fine-grained control over SAM connections
I made it parse INI-like configuration files, optionally, which allows it to
generate tunnels from snippets of i2pd tunnel configuration files. That's kinda
useful. It appears to be more-or-less compatible with i2pd's tunnels.conf
format, but it only supports the following options:
## binaries
type = server
host = 127.0.0.1
port = 8081
dir = /path/to/save/data/in #This is not shared with i2pd tunnels.conf
inbound.length = 6
outbound.length = 6
inbound.lengthVariance = 6
outbound.lengthVariance = 6
inbound.backupQuantity = 5
outbound.backupQuantity = 5
inbound.quantity = 15
outbound.quantity = 15
inbound.allowZeroHop = true
outbound.allowZeroHop = true
i2cp.encryptLeaseSet = true
gzip = true
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 4
i2cp.enableWhiteList = false
i2cp.enableBlackList = true
i2cp.accessList = BASE64KEYSSEPARATEDBY,COMMAS
keys = forwarder
The standalone application for configuring tunnels is named samcatd and it's
main package is in the directory ```./samcatd```. It works as a cli and is
capable of running a WebUI, which is currently view-only. In a future time, the
WebUI will also be capable of configuring and editing tunnels.
Also it doesn't support sections. Didn't realize that at first. Will address
soon.
Other options are added to the config structure, but have to be referenced
manually, there are no convenience functions for them.
## Static eepsite in like no seconds
Using this port forwarder, it's possible to create an instant eepsite from a
folder full of html files(and the resources they call upon). Probably obviously
to everybody reading this right now, but maybe not obviously to everyone reading
this forever. A go application that does this I call eephttpd can be built with
the command:
make server
and run from ./bin/eephttpd. The default behavior is to look for the files to
serve under the current directory in ./www. It can be configured to behave
differently according to the rules in [USAGE.md](USAGE.md). A Dockerfile is also
available.
## Quick-And-Dirty i2p-enabled golang web applications
Normal web applications can easily add the ability to serve itself over i2p by
importing and configuring this forwarding doodad. Wherever it takes the argument
for the web server's listening host and/or port, pass that same host and/or port
to a new instance of the "SAMForwarder" and then run the "Serve" function of the
SAMForwarder as a goroutine. This simply forwards the running service to the i2p
network, it doesn't do any filtering, and if your application establishes
out-of-band connections, those may escape. Also, if your application is
listening on all addresses, it will be visible from the local network.
Here's a simple example with a simple static file server:
```Diff
package main package main
import ( import (
"flag" "flag"
"log" "log"
"net/http" "net/http"
) )
> import "github.com/eyedeekay/sam-forwarder"
>
func main() { func main() {
port := flag.String("p", "8100", "port to serve on") port := flag.String("p", "8100", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host") directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse() flag.Parse()
>
> forwarder, err := samforwarder.NewSAMForwarderFromOptions(
> samforwarder.SetHost("127.0.0.1"),
> samforwarder.SetPort(*port),
> samforwarder.SetSAMHost("127.0.0.1"),
> samforwarder.SetSAMPort("7656"),
> samforwarder.SetName("staticfiles"),
> )
> if err != nil {
> log.Fatal(err.Error())
> }
> go forwarder.Serve()
http.Handle("/", http.FileServer(http.Dir(*directory))) http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port) log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil)) log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil))
} }
```
[This tiny file server taken from here and used for this example](https://gist.github.com/paulmach/7271283)
The previous application ephsite has been fully retired. If you were using it,
it can usually be replaced with ```samcatd -s``` and your existing arguments.
Current limitations:
====================
Datagrams are still a work-in-progress. They're enabled, but I don't know for
sure how well they'll work yet. TCP is pretty good though.
I need samcatd to accept a configuration folder identical to
/etc/i2pd/tunnels.conf.d, since part of the point of this is to be compatible
with i2pd's tunnels configuration. Once this is done, I'll resume turning it
into a .deb package.
I'm in the process of adding client proxying to a specific i2p destination by
base32 or (pre-added)jump address. TCP works well. UDP exists, but is not
thoroughly tested.
It doesn't encrypt the .i2pkeys file by default, so if someone can steal them,
then they can use them to construct tunnels to impersonate you. Experimental
support for encrypted saves has been added. The idea is that only the person
with the key will be able to decrypt and start the tunnels. It is up to the user
to determine how to go about managing these keys. Right now this system is
pretty bad. I'll be addressing that soon too.
Experimental support for KCP-based error correction and streaming-over-datagrams
is in the works. Some kind of reverse-proxy or filter is also an obvious choice.
I've only enabled the use of a subset of the i2cp and tunnel configuration
options, the ones I use the most and for no other real reason assume other
people use the most. They're pretty easy to add, it's just boring. *If you*
*want an i2cp or tunnel option that isn't available, bring it to my attention*
*please.* I'm pretty responsive when people actually contact me, it'll probably
be added within 24 hours.
be added within 24 hours. I intend to have configuration options for all
relevant i2cp and tunnel options, which I'm keeping track of
[here](config/CHECKLIST.md).
Encrypted leasesets are only half-implemented. The option seems to do nothing at
the moment. Soon it will be configurable.
I need to just change how the configuration is done entirely. I want it to work
with the configuration formats used by each I2P router.
I should probably have some options that are available in other general network
utilities like netcat and socat(ephsite may have it's name changed to samcat at
that point). Configuring timeouts and the like. In order to do this, some of the
existing flags should also be aliased to be more familiar and netcat-like.
TLS configuration is experimental. I have decided to implement optional,
automatically-configured self-signed TLS certificates. No CA support is planned
as an alternative CA would have to be used and no apparent option exists which
would be usable. If you're working on anything like that, I would like very
to know.
I want it to be able to save ini files based on the settings used for a running
forwarder. Should be easy, I just need to decide how I want to do it. Also to
focus a bit more.
## Stuff that's using it:
I've written a handful of example tools, but some of them might be better as
their own projects. An i2p-native static site generator in the style of jekyll
(but in go) could be cool.
Mostly mine, but this is all Free-as-in-Freedom for anyone to use:
Haha. Well shit. I migrated colluding\_sites\_attack to auto-configure using
the forwarder and the X-I2p-Dest* headers aren't passed through. Implies some
interesting arrangements, but also makes colluding\_sites\_attack useless in
it's present state. I mean I know what I did with si-i2p-plugin works, so it's
not that important. I'll have to look for a way to make this behavior
configurable though. On a related note, I finally know the difference between
http tunnels and server tunnels.
* [eephttpd](https://github.com/eyedeekay/eephttpd)
* [my fork of wikigopher](https://github.com/eyedeekay/wikigopher)
* [orangeforum](https://github.com/s-gv/orangeforum)
It would be really awesome if I could make this run on Android. So I'll make
that happen eventually.
Donate
------
TLS configuration is experimental. It might not be possible(To multiplex http
and https on the same SAM tunnel).
### Monero Wallet Address
XMR:43V6cTZrUfAb9JD6Dmn3vjdT9XxLbiE27D1kaoehb359ACaHs8191mR4RsJH7hGjRTiAoSwFQAVdsCBToXXPAqTMDdP2bZB
### Bitcoin Wallet Address
BTC:159M8MEUwhTzE9RXmcZxtigKaEjgfwRbHt
Index
-----
* [readme](index.html)
* [usage](usage.html)
* [configuration](packageconf.html)
* [embedding](embedding.html)
* [interface](interface.htnl)

View File

@@ -1,15 +1,20 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Hash: SHA512
# sam-forwarder
Forward a local port to i2p over the SAM API, or proxy a destination to a port
on the local host. This is a work-in-progress, but the basic functionality is,
there and it's already pretty useful. Everything TCP works, but UDP forwarding
is still not well tested, and UDP clients aren't enabled yet. I'm out of excuses
not to finish it now, too.
has much less real use than TCP. Turns out UDP was less broken than I thought
though. Yay. There's also a simple client-server VPN built on top of it,
eventually, it will be replaced with a peer-to-peer version.
Since it seems to be doing UDP now, if you'd like to donate to further
development there are some wallet addresses at the bottom of this readme for
now.
## building
Just:
make deps build
@@ -18,173 +23,120 @@ and it will be in the folder ./bin/
[![Build Status](https://travis-ci.org/eyedeekay/sam-forwarder.svg?branch=master)](https://travis-ci.org/eyedeekay/sam-forwarder)
## usage
## Usage:
./bin/ephsite -host=host -port=port
There are a number of ways to use sam-forwarder:
So, to serve an eepSite version of a local service on port 8080 -
### [usage/configuration](docs/USAGE.md) as an application(Start here for samcatd)
./bin/ephsite -host=127.0.0.1 -port=8080
### [embedding](docs/EMBEDDING.md) in other applications
For more information, [look here](USAGE.md)
### [encapsulate](docs/PACKAGECONF.md) configuration for i2p-enabled packages
## ini-like configuration
## binaries
I made it parse INI-like configuration files, optionally, which allows it to
generate tunnels from snippets of i2pd tunnel configuration files. That's kinda
useful. It appears to be more-or-less compatible with i2pd's tunnels.conf
format, but it only supports the following options:
Two binaries are produced by this repo. The first, ephsite, is only capable
of running one tunnel at a time and doesn't have VPN support. I'm only updating
it to make sure that the embeddable interface in existing applications doesn't
change. It will go away and be replaced with a wrapper to translate it to
'samcatd -s' commands whenever I complete [docs/CHECKLIST.md](docs/CHECKLIST.md).
type = server
host = 127.0.0.1
port = 8081
dir = /path/to/save/data/in #This is not shared with i2pd tunnels.conf
inbound.length = 6
outbound.length = 6
inbound.lengthVariance = 6
outbound.lengthVariance = 6
inbound.backupQuantity = 5
outbound.backupQuantity = 5
inbound.quantity = 15
outbound.quantity = 15
inbound.allowZeroHop = true
outbound.allowZeroHop = true
i2cp.encryptLeaseSet = true
gzip = true
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 4
i2cp.enableWhiteList = false
i2cp.enableBlackList = true
i2cp.accessList = BASE64KEYSSEPARATEDBY,COMMAS
keys = forwarder
Also it doesn't support sections. Didn't realize that at first. Will address
soon.
Other options are added to the config structure, but have to be referenced
manually, there are no convenience functions for them.
## Static eepsite in like no seconds
Using this port forwarder, it's possible to create an instant eepsite from a
folder full of html files(and the resources they call upon). Probably obviously
to everybody reading this right now, but maybe not obviously to everyone reading
this forever. A go application that does this I call eephttpd can be built with
the command:
make server
and run from ./bin/eephttpd. The default behavior is to look for the files to
serve under the current directory in ./www. It can be configured to behave
differently according to the rules in [USAGE.md](USAGE.md). A Dockerfile is also
available.
## Quick-And-Dirty i2p-enabled golang web applications
Normal web applications can easily add the ability to serve itself over i2p by
importing and configuring this forwarding doodad. Wherever it takes the argument
for the web server's listening host and/or port, pass that same host and/or port
to a new instance of the "SAMForwarder" and then run the "Serve" function of the
SAMForwarder as a goroutine. This simply forwards the running service to the i2p
network, it doesn't do any filtering, and if your application establishes
out-of-band connections, those may escape. Also, if your application is
listening on all addresses, it will be visible from the local network.
Here's a simple example with a simple static file server:
```Diff
package main package main
import ( import (
"flag" "flag"
"log" "log"
"net/http" "net/http"
) )
> import "github.com/eyedeekay/sam-forwarder"
>
func main() { func main() {
port := flag.String("p", "8100", "port to serve on") port := flag.String("p", "8100", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host") directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse() flag.Parse()
>
> forwarder, err := samforwarder.NewSAMForwarderFromOptions(
> samforwarder.SetHost("127.0.0.1"),
> samforwarder.SetPort(*port),
> samforwarder.SetSAMHost("127.0.0.1"),
> samforwarder.SetSAMPort("7656"),
> samforwarder.SetName("staticfiles"),
> )
> if err != nil {
> log.Fatal(err.Error())
> }
> go forwarder.Serve()
http.Handle("/", http.FileServer(http.Dir(*directory))) http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port) log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil)) log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil))
} }
```
[This tiny file server taken from here and used for this example](https://gist.github.com/paulmach/7271283)
The second, samcatd, is more advanced. It can start multiple tunnels with their
own settings, or be used to start tunnels on the fly like ephsite by passing the
- -s option. Eventually I'm probably just going to use this to configure all of my
tunnels.
Current limitations:
====================
Datagrams are still a work-in-progress. They're enabled, but I don't know for
sure how well they'll work yet. TCP is pretty good though.
I need to document it better.
[Besides fixing up the comments, this should help for now.](docs/USAGE.md). I
also need to control output verbosity better.
I'm in the process of adding client proxying to a specific i2p destination by
base32 or (pre-added)jump address. TCP works well. UDP exists, but is not
thoroughly tested.
I need samcatd to accept a configuration folder identical to
/etc/i2pd/tunnels.conf.d, since part of the point of this is to be compatible
with i2pd's tunnels configuration. Once this is done, I'll resume turning it
into a .deb package.
It doesn't encrypt the .i2pkeys file by default, so if someone can steal them,
then they can use them to construct tunnels to impersonate you. Experimental
support for encrypted saves has been added. The idea is that only the person
with the key will be able to decrypt and start the tunnels. It is up to the user
to determine how to go about managing these keys. Right now this system is
pretty bad. I'll be addressing that soon too.
TCP and UDP are both working now. Additional functionality might be added by
adding other kinds of protocols overtop the TCP and UDP tunnels as a primitive.
There's a very basic UDP-based VPN available in samcatd by configuration-file
only for now. Also it requires root. Probably need to split the VPN part into
it's own application. The package will need to give the application
CAP\_NET\_BIND\_SERVICE or something. This might work:
sudo setcap cap_net_bind_service=epi ./bin/samcatd
sudo setcap cap_net_bind_service=epi ./bin/samcatd-web
But I need to learn more about capabilities before I make that part of the
thing.
Some kind of reverse-proxy or filter is also an obvious choice.
I've only enabled the use of a subset of the i2cp and tunnel configuration
options, the ones I use the most and for no other real reason assume other
people use the most. They're pretty easy to add, it's just boring. *If you*
*want an i2cp or tunnel option that isn't available, bring it to my attention*
*please.* I'm pretty responsive when people actually contact me, it'll probably
be added within 24 hours.
Encrypted leasesets are only half-implemented. The option seems to do nothing at
the moment. Soon it will be configurable.
be added within 24 hours. I intend to have configuration options for all
relevant i2cp and tunnel options, which I'm keeping track of
[here](config/CHECKLIST.md).
I should probably have some options that are available in other general network
utilities like netcat and socat(ephsite may have it's name changed to samcat at
that point). Configuring timeouts and the like. In order to do this, some of the
existing flags should also be aliased to be more familiar and netcat-like.
utilities. I've started to do this with samcatd.
I want it to be able to save ini files based on the settings used for a running
forwarder. Should be easy, I just need to decide how I want to do it. Also to
focus a bit more.
focus a bit more. I've got more of a plan here now. tunconf has the loaded ini
file inside it, and variables to track the state of the config options while
running, and they can be switched to save options that might be changed via some
interface or another.
I've written a handful of example tools, but some of them might be better as
their own projects. An i2p-native static site generator in the style of jekyll
(but in go) could be cool.
Haha. Well shit. I migrated colluding\_sites\_attack to auto-configure using
the forwarder and the X-I2p-Dest* headers aren't passed through. Implies some
interesting arrangements, but also makes colluding\_sites\_attack useless in
it's present state. I mean I know what I did with si-i2p-plugin works, so it's
not that important. I'll have to look for a way to make this behavior
configurable though. On a related note, I finally know the difference between
http tunnels and server tunnels.
Example tools built using this are being broken off into their own repos. Use
the other repos where appropriate, so I can leave the examples un-messed with.
It would be really awesome if I could make this run on Android. So I'll make
that happen eventually.
that happen eventually. I started a daemon for managing multiple tunnels and I
figure I give it a web interface to configure stuff with. I'll probably put that
in a different repo though. This is looking a little cluttered.
TLS configuration is experimental. It might not be possible(To multiplex http
and https on the same SAM tunnel).
TLS configuration is experimental.
I've made it self-supervising, but I need to make better use of contexts.
## Stuff that's using it:
Mostly mine, but this is all Free-as-in-Freedom for anyone to use:
* [eephttpd](https://github.com/eyedeekay/eephttpd)
* [my fork of wikigopher](https://github.com/eyedeekay/wikigopher)
* [orangeforum](https://github.com/s-gv/orangeforum)
Donate
- ------
### Monero Wallet Address
XMR:43V6cTZrUfAb9JD6Dmn3vjdT9XxLbiE27D1kaoehb359ACaHs8191mR4RsJH7hGjRTiAoSwFQAVdsCBToXXPAqTMDdP2bZB
### Bitcoin Wallet Address
BTC:159M8MEUwhTzE9RXmcZxtigKaEjgfwRbHt
-----BEGIN PGP SIGNATURE-----
iQEzBAEBCAAdFiEEcNIGBzi++AUjrK/311wDs5teFOEFAluW3DMACgkQ11wDs5te
FOEtsAf9FPNwaocFwDStpEfWPs3ko8mI/34kJ+DXcCAFzWIKYimKD6vbOLl5vqIn
4HfGpsZaEMTVhW4kcAks9NQlDE3/yAMv7QRSX3pQTinXnXk13UdMbAG5oWUuKiSV
KBmqY7R9wwQu8JElW7iv84Ajl+9UrQeo5mMvp0jXkVbX0ZnCE/2spmhC+B1MySM3
df7ogmXbeoqOZc/FFGJjKGXtCLw8/MYuB7LfPCAoenOCVa2Hp17ujpPT4SyaXj29
bmhGCPdU0lf6Tp3IKXgi71nsIb7qtPSaY1f2B8n946YqXzT9/ys2BZ8OdvVPgZsP
P/DHK8YM/ayaciJ4RslbITaDygOR4A==
=bJY2
iQEzBAEBCgAdFiEEcNIGBzi++AUjrK/311wDs5teFOEFAlxfdWIACgkQ11wDs5te
FOH2Hwf+L63UsgKujukILs6/vPFe5rTvqVpM1NXko+49KcI8M0toiOS3Fqq66n4R
o3iy7bKR9W0wlkbvXrhCAI6QHT4C4Rv3lneN18+Lw3L5l7AzbSqa/+nHGj7IoVg3
5U8IH0HRv3LvAA4PJhmYmKCU/zO0Cblc8n1hFtVlT6Xby4NUNypqVRh9SK9NFg+i
AcenunoBMD6ggYR0nEZ9gKRW2LNY7+0kGc4oCwckQ5I9j1PIbhpwsQjVunLEUmd+
x1fFd4gzt4mnih06XkyVNbggMZQmgJ+BRv5kBMBlpfzrSsaFcolRRrvNeua2uLWm
3RZgd29GUvDU7OPALdbUcy0+a0Q6+g==
=0nQN
-----END PGP SIGNATURE-----

173
USAGE.md
View File

@@ -1,173 +0,0 @@
ephsite - Easy forwarding of local services to i2p
==================================================
ephsite is a forwarding proxy designed to configure a tunnel for use
with i2p. It can be used to easily forward a local service to the
i2p network using i2p's SAM API instead of the tunnel interface.
usage:
------
```
Usage of ./bin/ephsite:
-access string
Type of access list to use, can be "whitelist" "blacklist" or "none". (default "none")
-accesslist value
Specify an access list member(can be used multiple times)
-client
Client proxy mode(true or false)
-close
Close tunnel idle(true or false)
-closetime int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-dest string
Destination for client tunnels. Ignored for service tunnels. (default "none")
-dir string
Directory to save tunnel configuration file in.
-encryptlease
Use an encrypted leaseset(true or false) (default true)
-gzip
Uze gzip(true or false)
-host string
Target host(Host of service to forward to i2p) (default "127.0.0.1")
-inback int
Set inbound tunnel backup quantity(0 to 5) (default 4)
-incount int
Set inbound tunnel quantity(0 to 15) (default 6)
-ini string
Use an ini file for configuration(config file options override passed arguments for now.) (default "none")
-inlen int
Set inbound tunnel length(0 to 7) (default 3)
-invar int
Set inbound tunnel length variance(-7 to 7)
-lsk string
path to saved encrypted leaseset keys (default "none")
-name string
Tunnel name, this must be unique but can be anything. (default "forwarder")
-outback int
Set outbound tunnel backup quantity(0 to 5) (default 4)
-outcount int
Set outbound tunnel quantity(0 to 15) (default 6)
-outlen int
Set outbound tunnel length(0 to 7) (default 3)
-outvar int
Set outbound tunnel length variance(-7 to 7)
-port string
Target port(Port of service to forward to i2p) (default "8081")
-reduce
Reduce tunnel quantity when idle(true or false)
-reducecount int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-reducetime int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-samhost string
SAM host (default "127.0.0.1")
-samport string
SAM port (default "7656")
-save
Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.
-tlsport string
(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)
-udp
UDP mode(true or false)
-zeroin
Allow zero-hop, non-anonymous tunnels in(true or false)
-zeroout
Allow zero-hop, non-anonymous tunnels out(true or false)
```
eephttpd - Static file server automatically forwarded to i2p
============================================================
usage:
------
eephttpd is a static http server which automatically runs on i2p with
the help of the SAM bridge. By default it will only be available from
the localhost and it's i2p tunnel. It can be masked from the localhost
using a container.
```
Usage of ./bin/eephttpd:
-a string
hostname to serve on (default "127.0.0.1")
-c Use an encrypted leaseset(true or false)
-d string
the directory of static files to host(default ./www) (default "./www")
-f string
Use an ini file for configuration (default "none")
-g Uze gzip(true or false) (default true)
-i save i2p keys(and thus destinations) across reboots (default true)
-ib int
Set inbound tunnel backup quantity(0 to 5) (default 4)
-il int
Set inbound tunnel length(0 to 7) (default 3)
-iq int
Set inbound tunnel quantity(0 to 15) (default 8)
-iv int
Set inbound tunnel length variance(-7 to 7)
-l string
Type of access list to use, can be "whitelist" "blacklist" or "none". (default "none")
-m string
Certificate name to use (default "cert")
-n string
name to give the tunnel(default static-eepSite) (default "static-eepSite")
-ob int
Set outbound tunnel backup quantity(0 to 5) (default 4)
-ol int
Set outbound tunnel length(0 to 7) (default 3)
-oq int
Set outbound tunnel quantity(0 to 15) (default 8)
-ov int
Set outbound tunnel length variance(-7 to 7)
-p string
port to serve locally on (default "7880")
-r Reduce tunnel quantity when idle(true or false)
-rc int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-rt int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-s string
the directory to save the keys in(default ./) (default ".")
-sh string
sam host to connect to (default "127.0.0.1")
-sp string
sam port to connect to (default "7656")
-t Generate or use an existing TLS certificate
-z Allow zero-hop, non-anonymous tunnels(true or false)
```
### build in docker
```
docker build --build-arg user=eephttpd --build-arg path=example/www -f Dockerfile -t eyedeekay/eephttpd .
```
### Run in docker
```
docker run -i -t -d \
--name eephttpd-volume \
--volume eephttpd:/home/eephttpd/ \
eyedeekay/eephttpd
```
```
docker run -i -t -d \
--network si \
--env samhost=sam-host \
--env samport=7656 \
--env args=-r # Additional arguments to pass to eephttpd\
--network-alias eephttpd \
--hostname eephttpd \
--name eephttpd \
--restart always \
--volumes-from eephttpd-volume \
eyedeekay/eephttpd
```
instance
--------
a running instance of eephttpd with the example index file is availble on

107
config/CHECKLIST.md Normal file
View File

@@ -0,0 +1,107 @@
I2CP/Tunnel Options Implementation Checklist
============================================
This version of this document is valid for sam-forwarder. If you'd like to use
it, the original is at [CHECKLIST.orig.md](CHECKLIST.orig.md).
key:
- \[U\] - Undone/Unknown
- \[C\] - Confirmed Working
- \[W\] - Work in progress
- \[N\] - Not applicable/Won't be implemented without good reason.
- \[*\] - See also
Version Recommended Allowable Default
[U] - clientMessageTimeout 8*1000 - 120*1000 60*1000 The timeout (ms) for all sent messages. Unused. See the protocol specification for per-message settings.
[N] - crypto.lowTagThreshold 0.9.2 1-128 30 Minimum number of ElGamal/AES Session Tags before we send more. Recommended: approximately tagsToSend * 2/3
[N] - crypto.tagsToSend 0.9.2 1-128 40 Number of ElGamal/AES Session Tags to send at a time. For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
[U] - explicitPeers null Comma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
[C] - i2cp.dontPublishLeaseSet true,false false Should generally be set to true for clients and false for servers
[C] - i2cp.fastReceive 0.9.4 true,false false If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.messageReliability BestEffort, None BestEffort Guaranteed is disabled; None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
[U] - i2cp.password 0.8.2 string For authorization, if required by the router. If the client is running in the same JVM as a router, this option is not required. Warning - username and password are sent in the clear to the router, unless using SSL (i2cp.SSL=true). Authorization is only recommended when using SSL.
[U] - i2cp.username 0.8.2 string
[C] - inbound.allowZeroHop true,false true If incoming zero hop tunnel is allowed
[C] - outbound.allowZeroHop true,false true If outgoing zero hop tunnel is allowed
[C] - inbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels in
[C] - outbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels out
[U] - inbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[U] - outbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[C] - inbound.length 0 to 3 0 to 7 3 Length of tunnels in
[C] - outbound.length 0 to 3 0 to 7 3 Length of tunnels out
[C] - inbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels in. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[C] - outbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels out. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[U] - inbound.nickname string Name of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
[U] - outbound.nickname string Name of tunnel - generally ignored unless inbound.nickname is unset.
[U] - outbound.priority 0.9.4 -25 to 25 -25 to 25 0 Priority adjustment for outbound messages. Higher is higher priority.
[C] - inbound.quantity 1 to 3 1 to 16 2 Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are incompatible with older releases.
[C] - outbound.quantity 1 to 3 No limit 2 Number of tunnels out
[U] - inbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[U] - outbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[*] - inbound.* Any other options prefixed with "inbound." are stored in the "unknown options" properties of the inbound tunnel pool's settings.
[*] - outbound.* Any other options prefixed with "outbound." are stored in the "unknown options" properties of the outbound tunnel pool's settings.
[U] - shouldBundleReplyInfo 0.9.2 true,false true Set to false to disable ever bundling a reply LeaseSet. For clients that do not publish their LeaseSet, this option must be true for any reply to be possible. "true" is also recommended for multihomed servers with long connection times. Setting to "false" may save significant outbound bandwidth, especially if the client is configured with a large number of inbound tunnels (Leases). If replies are still required, this may shift the bandwidth burden to the far-end client and the floodfill. There are several cases where "false" may be appropriate: Unidirectional communication, no reply required LeaseSet is published and higher reply latency is acceptable LeaseSet is published, client is a "server", all connections are inbound so the connecting far-end destination obviously has the leaseset already. Connections are either short, or it is acceptable for latency on a long-lived connection to temporarily increase while the other end re-fetches the LeaseSet after expiration. HTTP servers may fit these requirements.
[C] - i2cp.closeIdleTime 0.7.1 1800000 300000 minimum (ms) Idle time required (default 30 minutes)
[C] - i2cp.closeOnIdle 0.7.1 true,false false Close I2P session when idle
[C] - i2cp.encryptLeaseSet 0.7.1 true,false false Encrypt the lease
[C] - i2cp.fastReceive 0.9.4 true,false true If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.gzip 0.6.5 true,false true Gzip outbound data
[C] - i2cp.leaseSetKey 0.7.1 For encrypted leasesets. Base 64 SessionKey (44 characters)
[C] - i2cp.leaseSetPrivateKey 0.9.18 Base 64 private key for encryption. Optionally preceded by the key type and ':'. Only "ELGAMAL_2048:" is supported, which is the default. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.leaseSetSigningPrivateKey 0.9.18 Base 64 private key for signatures. Optionally preceded by the key type and ':'. DSA_SHA1 is the default. Key type must match the signature type in the destination. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.reduceIdleTime 0.7.1 1200000 300000 minimum (ms) Idle time required (default 20 minutes, minimum 5 minutes)
[C] - i2cp.reduceOnIdle 0.7.1 true,false false Reduce tunnel quantity when idle
[C] - i2cp.reduceQuantity 0.7.1 1 1 to 5 1 Tunnel quantity when reduced (applies to both inbound and outbound)
[*] - i2cp.SSL 0.8.3 true,false false Connect to the router using SSL. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.host 127.0.0.1 Router hostname. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.port 1-65535 7654 Router I2CP port. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
Default Description
[C] - i2cp.accessList null Comma- or space-separated list of Base64 peer Hashes used for either access list or blocklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a allowlist for incoming connections. The name or number of the signature type for a transient destination. As of release 0.9.12.
[C] - i2cp.enableAccessList false Use the access list as a allowlist for incoming connections. As of release 0.7.13.
[C] - i2cp.enableBlackList false Use the access list as a blocklist for incoming connections. As of release 0.7.13.
[U] - i2p.streaming.answerPings true Whether to respond to incoming pings
[U] - i2p.streaming.blocklist null Comma- or space-separated list of Base64 peer Hashes to be blocklisted for incoming connections to ALL destinations in the context. This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.3.
[U] - i2p.streaming.bufferSize 64K How much transmit data (in bytes) will be accepted that hasn't been written out yet.
[U] - i2p.streaming.congestionAvoidanceGrowthRateFactor 1 When we're in congestion avoidance, we grow the window size at the rate of 1/(windowSize*factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.connectDelay -1 How long to wait after instantiating a new con before actually attempting to connect. If this is <= 0, connect immediately with no initial data. If greater than 0, wait until the output stream is flushed, the buffer fills, or that many milliseconds pass, and include any initial data with the SYN.
[U] - i2p.streaming.connectTimeout 5*60*1000 How long to block on connect, in milliseconds. Negative means indefinitely. Default is 5 minutes.
[U] - i2p.streaming.disableRejectLogging false Whether to disable warnings in the logs when an incoming connection is rejected due to connection limits. As of release 0.9.4.
[U] - i2p.streaming.dsalist null Comma- or space-separated list of Base64 peer Hashes or host names to be contacted using an alternate DSA destination. Only applies if multisession is enabled and the primary session is non-DSA (generally for shared clients only). This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.21.
[U] - i2p.streaming.enforceProtocol true Whether to listen only for the streaming protocol. Setting to true will prohibit communication with Destinations earlier than release 0.7.1 (released March 2009). Set to true if running multiple protocols on this Destination. As of release 0.9.1. Default true as of release 0.9.36.
[U] - i2p.streaming.inactivityAction 2 (send) (0=noop, 1=disconnect) What to do on an inactivity timeout - do nothing, disconnect, or send a duplicate ack.
[U] - i2p.streaming.inactivityTimeout 90*1000 Idle time before sending a keepalive
[U] - i2p.streaming.initialAckDelay 750 Delay before sending an ack
[U] - i2p.streaming.initialResendDelay 1000 The initial value of the resend delay field in the packet header, times 1000. Not fully implemented; see below.
[U] - i2p.streaming.initialRTO 9000 Initial timeout (if no sharing data available). As of release 0.9.8.
[U] - i2p.streaming.initialRTT 8000 Initial round trip time estimate (if no sharing data available). Disabled as of release 0.9.8; uses actual RTT.
[U] - i2p.streaming.initialWindowSize 6 (if no sharing data available) In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages.
[U] - i2p.streaming.limitAction reset What action to take when an incoming connection exceeds limits. Valid values are: reset (reset the connection); drop (drop the connection); or http (send a hardcoded HTTP 429 response). Any other value is a custom response to be sent. backslash-r and backslash-n will be replaced with CR and LF. As of release 0.9.34.
[U] - i2p.streaming.maxConcurrentStreams -1 (0 or negative value means unlimited) This is a total limit for incoming and outgoing combined.
[U] - i2p.streaming.maxConnsPerMinute 0 Incoming connection limit (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerHour 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerDay 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxMessageSize 1730 The MTU in bytes.
[U] - i2p.streaming.maxResends 8 Maximum number of retransmissions before failure.
[U] - i2p.streaming.maxTotalConnsPerMinute 0 Incoming connection limit (all peers; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerHour 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerDay 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxWindowSize 128
[U] - i2p.streaming.profile 1 (bulk) (2=interactive not supported) This doesn't currently do anything, but setting it to a value other than 1 will cause an error.
[U] - i2p.streaming.readTimeout -1 How long to block on read, in milliseconds. Negative means indefinitely.
[U] - i2p.streaming.slowStartGrowthRateFactor 1 When we're in slow start, we grow the window size at the rate of 1/(factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.tcbcache.rttDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.rttdevDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.wdwDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.writeTimeout -1 How long to block on write/flush, in milliseconds. Negative means indefinitely.
[C] - destination useful to consider adding to custom applications for client ocnfiguration
\* : I'd like to have something like this setting internal to samcatd, but it
might not always be relevant to pass it through to the real i2p router. Right
now, I'm leaning toward a samcatd specific setting, but maybe just alter the
behavior of this setting for use with samcatd instead? Probably just give
samcatd it's own thing.

97
config/CHECKLIST.orig.md Normal file
View File

@@ -0,0 +1,97 @@
I2CP/Tunnel Options Implementation Checklist
============================================
key:
- \[U\] - Undone/Unknoqn
- \[C\] - Confirmed Working
- \[W\] - Work in progress
- \[N\] - Not applicable
- \[*\] - See also
Version Recommended Allowable Default
[U] - clientMessageTimeout 8*1000 - 120*1000 60*1000 The timeout (ms) for all sent messages. Unused. See the protocol specification for per-message settings.
[U] - crypto.lowTagThreshold 0.9.2 1-128 30 Minimum number of ElGamal/AES Session Tags before we send more. Recommended: approximately tagsToSend * 2/3
[U] - crypto.tagsToSend 0.9.2 1-128 40 Number of ElGamal/AES Session Tags to send at a time. For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
[U] - explicitPeers null Comma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
[U] - i2cp.dontPublishLeaseSet true,false false Should generally be set to true for clients and false for servers
[U] - i2cp.fastReceive 0.9.4 true,false false If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[U] - i2cp.messageReliability BestEffort, None BestEffort Guaranteed is disabled; None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
[U] - i2cp.password 0.8.2 string For authorization, if required by the router. If the client is running in the same JVM as a router, this option is not required. Warning - username and password are sent in the clear to the router, unless using SSL (i2cp.SSL=true). Authorization is only recommended when using SSL.
[U] - i2cp.username 0.8.2 string
[U] - inbound.allowZeroHop true,false true If incoming zero hop tunnel is allowed
[U] - outbound.allowZeroHop true,false true If outgoing zero hop tunnel is allowed
[U] - inbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels in
[U] - outbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels out
[U] - inbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[U] - outbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[U] - inbound.length 0 to 3 0 to 7 3 Length of tunnels in
[U] - outbound.length 0 to 3 0 to 7 3 Length of tunnels out
[U] - inbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels in. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[U] - outbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels out. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[U] - inbound.nickname string Name of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
[U] - outbound.nickname string Name of tunnel - generally ignored unless inbound.nickname is unset.
[U] - outbound.priority 0.9.4 -25 to 25 -25 to 25 0 Priority adjustment for outbound messages. Higher is higher priority.
[U] - inbound.quantity 1 to 3 1 to 16 2 Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are incompatible with older releases.
[U] - outbound.quantity 1 to 3 No limit 2 Number of tunnels out
[U] - inbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[U] - outbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[U] - inbound.* Any other options prefixed with "inbound." are stored in the "unknown options" properties of the inbound tunnel pool's settings.
[U] - outbound.* Any other options prefixed with "outbound." are stored in the "unknown options" properties of the outbound tunnel pool's settings.
[U] - shouldBundleReplyInfo 0.9.2 true,false true Set to false to disable ever bundling a reply LeaseSet. For clients that do not publish their LeaseSet, this option must be true for any reply to be possible. "true" is also recommended for multihomed servers with long connection times. Setting to "false" may save significant outbound bandwidth, especially if the client is configured with a large number of inbound tunnels (Leases). If replies are still required, this may shift the bandwidth burden to the far-end client and the floodfill. There are several cases where "false" may be appropriate: Unidirectional communication, no reply required LeaseSet is published and higher reply latency is acceptable LeaseSet is published, client is a "server", all connections are inbound so the connecting far-end destination obviously has the leaseset already. Connections are either short, or it is acceptable for latency on a long-lived connection to temporarily increase while the other end re-fetches the LeaseSet after expiration. HTTP servers may fit these requirements.
[U] - i2cp.closeIdleTime 0.7.1 1800000 300000 minimum (ms) Idle time required (default 30 minutes)
[U] - i2cp.closeOnIdle 0.7.1 true,false false Close I2P session when idle
[U] - i2cp.encryptLeaseSet 0.7.1 true,false false Encrypt the lease
[U] - i2cp.gzip 0.6.5 true,false true Gzip outbound data
[U] - i2cp.leaseSetKey 0.7.1 For encrypted leasesets. Base 64 SessionKey (44 characters)
[U] - i2cp.leaseSetPrivateKey 0.9.18 Base 64 private key for encryption. Optionally preceded by the key type and ':'. Only "ELGAMAL_2048:" is supported, which is the default. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[U] - i2cp.leaseSetSigningPrivateKey 0.9.18 Base 64 private key for signatures. Optionally preceded by the key type and ':'. DSA_SHA1 is the default. Key type must match the signature type in the destination. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[U] - i2cp.reduceIdleTime 0.7.1 1200000 300000 minimum (ms) Idle time required (default 20 minutes, minimum 5 minutes)
[U] - i2cp.reduceOnIdle 0.7.1 true,false false Reduce tunnel quantity when idle
[U] - i2cp.reduceQuantity 0.7.1 1 1 to 5 1 Tunnel quantity when reduced (applies to both inbound and outbound)
[U] - i2cp.SSL 0.8.3 true,false false Connect to the router using SSL. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[U] - i2cp.tcp.host 127.0.0.1 Router hostname. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[U] - i2cp.tcp.port 1-65535 7654 Router I2CP port. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
Default Description
[U] - i2cp.accessList null Comma- or space-separated list of Base64 peer Hashes used for either access list or blocklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a allowlist for incoming connections. The name or number of the signature type for a transient destination. As of release 0.9.12.
[U] - i2cp.enableAccessList false Use the access list as a allowlist for incoming connections. As of release 0.7.13.
[U] - i2cp.enableBlackList false Use the access list as a blocklist for incoming connections. As of release 0.7.13.
[U] - i2p.streaming.answerPings true Whether to respond to incoming pings
[U] - i2p.streaming.blocklist null Comma- or space-separated list of Base64 peer Hashes to be blocklisted for incoming connections to ALL destinations in the context. This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.3.
[U] - i2p.streaming.bufferSize 64K How much transmit data (in bytes) will be accepted that hasn't been written out yet.
[U] - i2p.streaming.congestionAvoidanceGrowthRateFactor 1 When we're in congestion avoidance, we grow the window size at the rate of 1/(windowSize*factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.connectDelay -1 How long to wait after instantiating a new con before actually attempting to connect. If this is <= 0, connect immediately with no initial data. If greater than 0, wait until the output stream is flushed, the buffer fills, or that many milliseconds pass, and include any initial data with the SYN.
[U] - i2p.streaming.connectTimeout 5*60*1000 How long to block on connect, in milliseconds. Negative means indefinitely. Default is 5 minutes.
[U] - i2p.streaming.disableRejectLogging false Whether to disable warnings in the logs when an incoming connection is rejected due to connection limits. As of release 0.9.4.
[U] - i2p.streaming.dsalist null Comma- or space-separated list of Base64 peer Hashes or host names to be contacted using an alternate DSA destination. Only applies if multisession is enabled and the primary session is non-DSA (generally for shared clients only). This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.21.
[U] - i2p.streaming.enforceProtocol true Whether to listen only for the streaming protocol. Setting to true will prohibit communication with Destinations earlier than release 0.7.1 (released March 2009). Set to true if running multiple protocols on this Destination. As of release 0.9.1. Default true as of release 0.9.36.
[U] - i2p.streaming.inactivityAction 2 (send) (0=noop, 1=disconnect) What to do on an inactivity timeout - do nothing, disconnect, or send a duplicate ack.
[U] - i2p.streaming.inactivityTimeout 90*1000 Idle time before sending a keepalive
[U] - i2p.streaming.initialAckDelay 750 Delay before sending an ack
[U] - i2p.streaming.initialResendDelay 1000 The initial value of the resend delay field in the packet header, times 1000. Not fully implemented; see below.
[U] - i2p.streaming.initialRTO 9000 Initial timeout (if no sharing data available). As of release 0.9.8.
[U] - i2p.streaming.initialRTT 8000 Initial round trip time estimate (if no sharing data available). Disabled as of release 0.9.8; uses actual RTT.
[U] - i2p.streaming.initialWindowSize 6 (if no sharing data available) In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages.
[U] - i2p.streaming.limitAction reset What action to take when an incoming connection exceeds limits. Valid values are: reset (reset the connection); drop (drop the connection); or http (send a hardcoded HTTP 429 response). Any other value is a custom response to be sent. backslash-r and backslash-n will be replaced with CR and LF. As of release 0.9.34.
[U] - i2p.streaming.maxConcurrentStreams -1 (0 or negative value means unlimited) This is a total limit for incoming and outgoing combined.
[U] - i2p.streaming.maxConnsPerMinute 0 Incoming connection limit (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerHour 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerDay 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxMessageSize 1730 The MTU in bytes.
[U] - i2p.streaming.maxResends 8 Maximum number of retransmissions before failure.
[U] - i2p.streaming.maxTotalConnsPerMinute 0 Incoming connection limit (all peers; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerHour 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerDay 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxWindowSize 128
[U] - i2p.streaming.profile 1 (bulk) (2=interactive not supported) This doesn't currently do anything, but setting it to a value other than 1 will cause an error.
[U] - i2p.streaming.readTimeout -1 How long to block on read, in milliseconds. Negative means indefinitely.
[U] - i2p.streaming.slowStartGrowthRateFactor 1 When we're in slow start, we grow the window size at the rate of 1/(factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.tcbcache.rttDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.rttdevDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.wdwDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.writeTimeout -1 How long to block on write/flush, in milliseconds. Negative means indefinitely.
[U] - destination useful to consider adding to custom applications for client ocnfiguration

1
config/README.md Symbolic link
View File

@@ -0,0 +1 @@
CHECKLIST.md

68
config/access.go Normal file
View File

@@ -0,0 +1,68 @@
package i2ptunconf
import (
"strings"
)
// GetAccessListType takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetAccessListType(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
return c.AccessListType
}
// SetAccessListType sets the access list type from a config file
func (c *Conf) SetAccessListType(label ...string) {
if v, ok := c.GetBool("i2cp.enableBlackList", label...); ok {
if v {
c.AccessListType = "blocklist"
}
}
if v, ok := c.GetBool("i2cp.enableAccessList", label...); ok {
if v {
c.AccessListType = "allowlist"
}
}
if c.AccessListType != "allowlist" && c.AccessListType != "blocklist" {
c.AccessListType = "none"
}
}
// AddAccessListMember adds a member to either the blocklist or the allowlist
func (c *Conf) AddAccessListMember(key string) {
for _, item := range c.AccessList {
if item == key {
return
}
}
c.AccessList = append(c.AccessList, key)
}
func (c *Conf) accesslisttype() string {
if c.AccessListType == "allowlist" {
return "i2cp.enableAccessList=true"
} else if c.AccessListType == "blocklist" {
return "i2cp.enableBlackList=true"
} else if c.AccessListType == "none" {
return ""
}
return ""
}
func (c *Conf) accesslist() string {
if c.AccessListType != "" && len(c.AccessList) > 0 {
r := ""
for _, s := range c.AccessList {
r += s + ","
}
return "i2cp.accessList=" + strings.TrimSuffix(r, ",")
}
return ""
}

1
config/auth.go Normal file
View File

@@ -0,0 +1 @@
package i2ptunconf

53
config/backups.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetInBackups takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetInBackups(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("inbound.backupQuantity", label...); o {
return x
}
return arg
}
// GetOutBackups takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetOutBackups(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("outbound.backupQuantity", label...); o {
return x
}
return arg
}
// SetInBackups sets the inbound tunnel backups from config file
func (c *Conf) SetInBackups(label ...string) {
if v, ok := c.GetInt("inbound.backupQuantity", label...); ok {
c.InBackupQuantity = v
} else {
c.InBackupQuantity = 2
}
}
// SetOutBackups sets the outbound tunnel backups from config file
func (c *Conf) SetOutBackups(label ...string) {
if v, ok := c.GetInt("outbound.backupQuantity", label...); ok {
c.OutBackupQuantity = v
} else {
c.OutBackupQuantity = 2
}
}

1
config/bundle.go Normal file
View File

@@ -0,0 +1 @@
package i2ptunconf

27
config/compress.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetUseCompression takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetUseCompression(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("gzip", label...); o {
return x
}
return arg
}
// SetCompressed sets the compression from the config file
func (c *Conf) SetCompressed(label ...string) {
if v, ok := c.GetBool("gzip", label...); ok {
c.UseCompression = v
} else {
c.UseCompression = true
}
}

182
config/conf.go Normal file
View File

@@ -0,0 +1,182 @@
package i2ptunconf
import (
"fmt"
"strings"
)
import (
sfi2pkeys "github.com/eyedeekay/sam-forwarder/i2pkeys"
"github.com/eyedeekay/sam3/i2pkeys"
)
var err error
func (f *Conf) ID() string {
return f.TunName
}
func (f *Conf) Keys() i2pkeys.I2PKeys {
return f.LoadedKeys
}
func (f *Conf) Cleanup() {
}
func (f *Conf) GetType() string {
return f.Type
}
/*func (f *Conf) targetForPort443() string {
if f.TargetForPort443 != "" {
return "targetForPort.4443=" + f.TargetHost + ":" + f.TargetForPort443
}
return ""
}*/
func (f *Conf) print() []string {
lsk, lspk, lspsk := f.leasesetsettings()
return []string{
//f.targetForPort443(),
"inbound.length=" + fmt.Sprintf("%d", f.InLength),
"outbound.length=" + fmt.Sprintf("%d", f.OutLength),
"inbound.lengthVariance=" + fmt.Sprintf("%d", f.InVariance),
"outbound.lengthVariance=" + fmt.Sprintf("%d", f.OutVariance),
"inbound.backupQuantity=" + fmt.Sprintf("%d", f.InBackupQuantity),
"outbound.backupQuantity=" + fmt.Sprintf("%d", f.OutBackupQuantity),
"inbound.quantity=" + fmt.Sprintf("%d", f.InQuantity),
"outbound.quantity=" + fmt.Sprintf("%d", f.OutQuantity),
"inbound.allowZeroHop=" + fmt.Sprintf("%v", f.InAllowZeroHop),
"outbound.allowZeroHop=" + fmt.Sprintf("%v", f.OutAllowZeroHop),
"i2cp.fastRecieve=" + fmt.Sprintf("%v", f.FastRecieve),
"i2cp.gzip=" + fmt.Sprintf("%v", f.UseCompression),
"i2cp.reduceOnIdle=" + fmt.Sprintf("%v", f.ReduceIdle),
"i2cp.reduceIdleTime=" + fmt.Sprintf("%v", f.ReduceIdleTime),
"i2cp.reduceQuantity=" + fmt.Sprintf("%d", f.ReduceIdleQuantity),
"i2cp.closeOnIdle=" + fmt.Sprintf("%v", f.CloseIdle),
"i2cp.closeIdleTime=" + fmt.Sprintf("%d", f.CloseIdleTime),
"i2cp.messageReliability=" + f.MessageReliability,
"i2cp.encryptLeaseSet=" + fmt.Sprintf("%v", f.EncryptLeaseSet),
"i2cp.leaseSetEncType=" + fmt.Sprintf("%s", f.LeaseSetEncType),
lsk, lspk, lspsk,
f.accesslisttype(),
f.accesslist(),
}
}
func (f *Conf) Props() map[string]string {
r := make(map[string]string)
print := f.print()
print = append(print, "base32="+f.Base32())
print = append(print, "base64="+f.Base64())
print = append(print, "base32words="+f.Base32Readable())
for _, prop := range print {
k, v := sfi2pkeys.Prop(prop)
r[k] = v
}
return r
}
func (f *Conf) Print() string {
var r string
r += "name=" + f.TunName + "\n"
r += "type=" + f.Type + "\n"
if f.Type == "http" {
r += "httpserver\n"
} else {
r += "ntcpserver\n"
}
for _, s := range f.print() {
r += s + "\n"
}
return strings.Replace(r, "\n\n", "\n", -1)
}
func (f *Conf) Search(search string) string {
terms := strings.Split(search, ",")
if search == "" {
return f.Print()
}
for _, value := range terms {
if !strings.Contains(f.Print(), value) {
return ""
}
}
return f.Print()
}
/*
func (f *Conf) accesslisttype() string {
if f.accessListType == "allowlist" {
return "i2cp.enableAccessList=true"
} else if f.accessListType == "blocklist" {
return "i2cp.enableBlackList=true"
} else if f.accessListType == "none" {
return ""
}
return ""
}
func (f *Conf) accesslist() string {
if f.accessListType != "" && len(f.accessList) > 0 {
r := ""
for _, s := range f.accessList {
r += s + ","
}
return "i2cp.accessList=" + strings.TrimSuffix(r, ",")
}
return ""
}
*/
func (f *Conf) leasesetsettings() (string, string, string) {
var r, s, t string
if f.LeaseSetKey != "" {
r = "i2cp.leaseSetKey=" + f.LeaseSetKey
}
if f.LeaseSetPrivateKey != "" {
s = "i2cp.leaseSetPrivateKey=" + f.LeaseSetPrivateKey
}
if f.LeaseSetPrivateSigningKey != "" {
t = "i2cp.leaseSetPrivateSigningKey=" + f.LeaseSetPrivateSigningKey
}
return r, s, t
}
// Target returns the host:port of the local service you want to forward to i2p
func (f *Conf) Target() string {
return f.TargetHost + ":" + f.TargetPort
}
func (f *Conf) sam() string {
return f.SamHost + ":" + f.SamPort
}
//Base32 returns the base32 address where the local service is being forwarded
func (f *Conf) Base32() string {
return f.LoadedKeys.Addr().Base32()
}
//Base32Readable will always be an empty string when used here.
func (f *Conf) Base32Readable() string {
return ""
}
//Base64 returns the base64 address where the local service is being forwarded
func (f *Conf) Base64() string {
return f.LoadedKeys.Addr().Base64()
}
//Serve starts the SAM connection and and forwards the local host:port to i2p
func (f *Conf) Serve() error {
return nil
}
func (f *Conf) Up() bool {
return false
}
//Close shuts the whole thing down.
func (f *Conf) Close() error {
return nil
}

20
config/config-options.go Normal file
View File

@@ -0,0 +1,20 @@
package i2ptunconf
//Option is a Conf Option
type Option func(*Conf) error
//SetTargetForPort sets the port of the Conf's SAM bridge using a string
/*func SetTargetForPort443(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.TargetForPort443 = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
*/

53
config/controlhostport.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetHost takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetControlHost(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("controlhost", label...); o {
return x
}
return arg
}
// GetPort takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetControlPort(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("controlport", label...); o {
return x
}
return arg
}
// SetHost sets the host to forward from the config file
func (c *Conf) SetControlHost(label ...string) {
if v, ok := c.Get("controlhost", label...); ok {
c.ControlHost = v
} else {
c.ControlHost = "127.0.0.1"
}
}
// SetPort sets the port to forward from the config file
func (c *Conf) SetControlPort(label ...string) {
if v, ok := c.Get("controlport", label...); ok {
c.ControlPort = v
} else {
c.ControlPort = ""
}
}

27
config/cryptsave.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetKeyFile takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetKeyFile(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("keyfile", label...); o {
return x
}
return arg
}
// SetKeyFile sets the key save directory from the config file
func (c *Conf) SetKeyFile(label ...string) {
if v, ok := c.Get("keyfile", label...); ok {
c.KeyFilePath = v
} else {
c.KeyFilePath = "./"
}
}

27
config/dest.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetClientDest takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetClientDest(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("destination", label...); o {
return x
}
return arg
}
// SetClientDest sets the key name from the config file
func (c *Conf) SetClientDest(label ...string) {
if v, ok := c.Get("destination", label...); ok {
c.ClientDest = v
} else {
c.ClientDest = ""
}
}

29
config/dir.go Normal file
View File

@@ -0,0 +1,29 @@
package i2ptunconf
//
// GetDir takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetDir(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("dir", label...); o {
return x
}
return arg
}
// SetDir sets the key save directory from the config file
func (c *Conf) SetDir(label ...string) {
if v, ok := c.Get("dir", label...); ok {
c.SaveDirectory = v
} else {
c.SaveDirectory = "./"
}
}

27
config/endpoint.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetEndpointHost takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetEndpointHost(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("tunhost", label...); o {
return x
}
return arg
}
// SetEndpointHost sets the host to forward from the config file
func (c *Conf) SetEndpointHost(label ...string) {
if v, ok := c.Get("tunhost", label...); ok {
c.TunnelHost = v
} else {
c.TunnelHost = "10.79.0.1"
}
}

27
config/fastrecieve.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetFastRecieve takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetFastRecieve(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("i2cp.fastRecieve", label...); o {
return x
}
return arg
}
// SetFastRecieve sets the compression from the config file
func (c *Conf) SetFastRecieve(label ...string) {
if v, ok := c.GetBool("i2cp.fastRecieve", label...); ok {
c.FastRecieve = v
} else {
c.FastRecieve = false
}
}

1
config/helpers/helper.go Normal file
View File

@@ -0,0 +1 @@
package i2ptunhelper

View File

@@ -0,0 +1,226 @@
package i2ptunhelper
import (
"github.com/eyedeekay/httptunnel"
"github.com/eyedeekay/httptunnel/multiproxy"
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/options"
"github.com/eyedeekay/sam-forwarder/tcp"
"github.com/eyedeekay/sam-forwarder/udp"
)
func NewSAMHTTPClientFromConf(config *i2ptunconf.Conf) (*i2phttpproxy.SAMHTTPProxy, error) {
if config != nil {
return i2phttpproxy.NewHttpProxy(
i2phttpproxy.SetName(config.TunName),
i2phttpproxy.SetKeysPath(config.KeyFilePath),
i2phttpproxy.SetHost(config.SamHost),
i2phttpproxy.SetPort(config.SamPort),
i2phttpproxy.SetProxyAddr(config.TargetHost+":"+config.TargetPort),
i2phttpproxy.SetControlHost(config.ControlHost),
i2phttpproxy.SetControlPort(config.ControlPort),
i2phttpproxy.SetInLength(uint(config.InLength)),
i2phttpproxy.SetOutLength(uint(config.OutLength)),
i2phttpproxy.SetInQuantity(uint(config.InQuantity)),
i2phttpproxy.SetOutQuantity(uint(config.OutQuantity)),
i2phttpproxy.SetInBackups(uint(config.InBackupQuantity)),
i2phttpproxy.SetOutBackups(uint(config.OutBackupQuantity)),
i2phttpproxy.SetInVariance(config.InVariance),
i2phttpproxy.SetOutVariance(config.OutVariance),
i2phttpproxy.SetUnpublished(config.Client),
i2phttpproxy.SetReduceIdle(config.ReduceIdle),
i2phttpproxy.SetCompression(config.UseCompression),
i2phttpproxy.SetReduceIdleTime(uint(config.ReduceIdleTime)),
i2phttpproxy.SetReduceIdleQuantity(uint(config.ReduceIdleQuantity)),
i2phttpproxy.SetCloseIdle(config.CloseIdle),
i2phttpproxy.SetCloseIdleTime(uint(config.CloseIdleTime)),
)
}
return nil, nil
}
// NewSAMClientForwarderFromConfig generates a new SAMForwarder from a config file
func NewSAMHTTPClientFromConfig(iniFile, SamHost, SamPort string, label ...string) (*i2phttpproxy.SAMHTTPProxy, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMHTTPClientFromConf(config)
}
return nil, nil
}
func NewSAMBrowserClientFromConf(config *i2ptunconf.Conf) (*i2pbrowserproxy.SAMMultiProxy, error) {
if config != nil {
return i2pbrowserproxy.NewHttpProxy(
i2pbrowserproxy.SetName(config.TunName),
i2pbrowserproxy.SetKeysPath(config.KeyFilePath),
i2pbrowserproxy.SetHost(config.SamHost),
i2pbrowserproxy.SetPort(config.SamPort),
i2pbrowserproxy.SetProxyAddr(config.TargetHost+":"+config.TargetPort),
i2pbrowserproxy.SetControlHost(config.ControlHost),
i2pbrowserproxy.SetControlPort(config.ControlPort),
i2pbrowserproxy.SetInLength(uint(config.InLength)),
i2pbrowserproxy.SetOutLength(uint(config.OutLength)),
i2pbrowserproxy.SetInQuantity(uint(config.InQuantity)),
i2pbrowserproxy.SetOutQuantity(uint(config.OutQuantity)),
i2pbrowserproxy.SetInBackups(uint(config.InBackupQuantity)),
i2pbrowserproxy.SetOutBackups(uint(config.OutBackupQuantity)),
i2pbrowserproxy.SetInVariance(config.InVariance),
i2pbrowserproxy.SetOutVariance(config.OutVariance),
i2pbrowserproxy.SetUnpublished(config.Client),
i2pbrowserproxy.SetReduceIdle(config.ReduceIdle),
i2pbrowserproxy.SetCompression(config.UseCompression),
i2pbrowserproxy.SetReduceIdleTime(uint(config.ReduceIdleTime)),
i2pbrowserproxy.SetReduceIdleQuantity(uint(config.ReduceIdleQuantity)),
//i2pbrowserproxy.SetCloseIdle(config.CloseIdle),
//i2pbrowserproxy.SetCloseIdleTime(uint(config.CloseIdleTime)),
)
}
return nil, nil
}
func NewSAMBrowserClientFromConfig(iniFile, SamHost, SamPort string, label ...string) (*i2pbrowserproxy.SAMMultiProxy, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMBrowserClientFromConf(config)
}
return nil, nil
}
// NewSAMClientForwarderFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewSAMClientForwarderFromConf(config *i2ptunconf.Conf) (*samforwarder.SAMClientForwarder, error) {
if config != nil {
return samforwarder.NewSAMClientForwarderFromOptions(
samoptions.SetSaveFile(config.SaveFile),
samoptions.SetFilePath(config.SaveDirectory),
samoptions.SetHost(config.TargetHost),
samoptions.SetPort(config.TargetPort),
samoptions.SetSAMHost(config.SamHost),
samoptions.SetSAMPort(config.SamPort),
samoptions.SetSigType(config.SigType),
samoptions.SetName(config.TunName),
samoptions.SetInLength(config.InLength),
samoptions.SetOutLength(config.OutLength),
samoptions.SetInVariance(config.InVariance),
samoptions.SetOutVariance(config.OutVariance),
samoptions.SetInQuantity(config.InQuantity),
samoptions.SetOutQuantity(config.OutQuantity),
samoptions.SetInBackups(config.InBackupQuantity),
samoptions.SetOutBackups(config.OutBackupQuantity),
samoptions.SetEncrypt(config.EncryptLeaseSet),
samoptions.SetLeaseSetKey(config.LeaseSetKey),
samoptions.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samoptions.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samoptions.SetAllowZeroIn(config.InAllowZeroHop),
samoptions.SetAllowZeroOut(config.OutAllowZeroHop),
samoptions.SetFastRecieve(config.FastRecieve),
samoptions.SetCompress(config.UseCompression),
samoptions.SetReduceIdle(config.ReduceIdle),
samoptions.SetReduceIdleTimeMs(config.ReduceIdleTime),
samoptions.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samoptions.SetCloseIdle(config.CloseIdle),
samoptions.SetCloseIdleTimeMs(config.CloseIdleTime),
samoptions.SetAccessListType(config.AccessListType),
samoptions.SetAccessList(config.AccessList),
samoptions.SetMessageReliability(config.MessageReliability),
samoptions.SetPassword(config.KeyFilePath),
samoptions.SetDestination(config.ClientDest),
)
}
return nil, nil
}
// NewSAMClientForwarderFromConfig generates a new SAMForwarder from a config file
func NewSAMClientForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarder.SAMClientForwarder, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMClientForwarderFromConf(config)
}
return nil, nil
}
// NewSAMDGClientForwarderFromConf generates a SAMSSUforwarder from *i2ptunconf.Conf
func NewSAMDGClientForwarderFromConf(config *i2ptunconf.Conf) (*samforwarderudp.SAMDGClientForwarder, error) {
if config != nil {
return samforwarderudp.NewSAMDGClientForwarderFromOptions(
samoptions.SetSaveFile(config.SaveFile),
samoptions.SetFilePath(config.SaveDirectory),
samoptions.SetHost(config.TargetHost),
samoptions.SetPort(config.TargetPort),
samoptions.SetSAMHost(config.SamHost),
samoptions.SetSAMPort(config.SamPort),
samoptions.SetSigType(config.SigType),
samoptions.SetName(config.TunName),
samoptions.SetInLength(config.InLength),
samoptions.SetOutLength(config.OutLength),
samoptions.SetInVariance(config.InVariance),
samoptions.SetOutVariance(config.OutVariance),
samoptions.SetInQuantity(config.InQuantity),
samoptions.SetOutQuantity(config.OutQuantity),
samoptions.SetInBackups(config.InBackupQuantity),
samoptions.SetOutBackups(config.OutBackupQuantity),
samoptions.SetEncrypt(config.EncryptLeaseSet),
samoptions.SetLeaseSetKey(config.LeaseSetKey),
samoptions.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samoptions.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samoptions.SetAllowZeroIn(config.InAllowZeroHop),
samoptions.SetAllowZeroOut(config.OutAllowZeroHop),
samoptions.SetFastRecieve(config.FastRecieve),
samoptions.SetCompress(config.UseCompression),
samoptions.SetReduceIdle(config.ReduceIdle),
samoptions.SetReduceIdleTimeMs(config.ReduceIdleTime),
samoptions.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samoptions.SetCloseIdle(config.CloseIdle),
samoptions.SetCloseIdleTimeMs(config.CloseIdleTime),
samoptions.SetAccessListType(config.AccessListType),
samoptions.SetAccessList(config.AccessList),
samoptions.SetMessageReliability(config.MessageReliability),
samoptions.SetPassword(config.KeyFilePath),
samoptions.SetDestination(config.ClientDest),
)
}
return nil, nil
}
func NewSAMDGClientForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarderudp.SAMDGClientForwarder, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMDGClientForwarderFromConf(config)
}
return nil, nil
}

View File

@@ -0,0 +1,130 @@
package i2ptunhelper
import (
"github.com/eyedeekay/outproxy"
"github.com/eyedeekay/sam-forwarder/config"
)
// NewOutProxyFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewOutProxyFromConf(config *i2ptunconf.Conf) (*outproxy.OutProxy, error) {
if config != nil {
return outproxy.NewOutProxyFromOptions(
outproxy.SetType(config.Type),
outproxy.SetSaveFile(config.SaveFile),
outproxy.SetFilePath(config.SaveDirectory),
outproxy.SetHost(config.TargetHost),
outproxy.SetPort(config.TargetPort),
outproxy.SetSAMHost(config.SamHost),
outproxy.SetSAMPort(config.SamPort),
outproxy.SetSigType(config.SigType),
outproxy.SetName(config.TunName),
outproxy.SetInLength(config.InLength),
outproxy.SetOutLength(config.OutLength),
outproxy.SetInVariance(config.InVariance),
outproxy.SetOutVariance(config.OutVariance),
outproxy.SetInQuantity(config.InQuantity),
outproxy.SetOutQuantity(config.OutQuantity),
outproxy.SetInBackups(config.InBackupQuantity),
outproxy.SetOutBackups(config.OutBackupQuantity),
outproxy.SetEncrypt(config.EncryptLeaseSet),
outproxy.SetLeaseSetKey(config.LeaseSetKey),
outproxy.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
outproxy.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
outproxy.SetAllowZeroIn(config.InAllowZeroHop),
outproxy.SetAllowZeroOut(config.OutAllowZeroHop),
outproxy.SetFastRecieve(config.FastRecieve),
outproxy.SetCompress(config.UseCompression),
outproxy.SetReduceIdle(config.ReduceIdle),
outproxy.SetReduceIdleTimeMs(config.ReduceIdleTime),
outproxy.SetReduceIdleQuantity(config.ReduceIdleQuantity),
outproxy.SetCloseIdle(config.CloseIdle),
outproxy.SetCloseIdleTimeMs(config.CloseIdleTime),
outproxy.SetAccessListType(config.AccessListType),
outproxy.SetAccessList(config.AccessList),
outproxy.SetMessageReliability(config.MessageReliability),
outproxy.SetKeyFile(config.KeyFilePath),
//outproxy.SetTargetForPort443(config.TargetForPort443),
)
}
return nil, nil
}
// NewOutProxyFromConfig generates a new OutProxy from a config file
func NewOutProxyFromConfig(iniFile, SamHost, SamPort string, label ...string) (*outproxy.HttpOutProxy, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewHttpOutProxyFromConf(config)
}
return nil, nil
}
// NewOutProxyFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewHttpOutProxyFromConf(config *i2ptunconf.Conf) (*outproxy.HttpOutProxy, error) {
if config != nil {
return outproxy.NewHttpOutProxydFromOptions(
outproxy.SetHttpType(config.Type),
outproxy.SetHttpSaveFile(config.SaveFile),
outproxy.SetHttpFilePath(config.SaveDirectory),
outproxy.SetHttpHost(config.TargetHost),
outproxy.SetHttpPort(config.TargetPort),
outproxy.SetHttpSAMHost(config.SamHost),
outproxy.SetHttpSAMPort(config.SamPort),
outproxy.SetHttpSigType(config.SigType),
outproxy.SetHttpName(config.TunName),
outproxy.SetHttpInLength(config.InLength),
outproxy.SetHttpOutLength(config.OutLength),
outproxy.SetHttpInVariance(config.InVariance),
outproxy.SetHttpOutVariance(config.OutVariance),
outproxy.SetHttpInQuantity(config.InQuantity),
outproxy.SetHttpOutQuantity(config.OutQuantity),
outproxy.SetHttpInBackups(config.InBackupQuantity),
outproxy.SetHttpOutBackups(config.OutBackupQuantity),
outproxy.SetHttpEncrypt(config.EncryptLeaseSet),
outproxy.SetHttpLeaseSetKey(config.LeaseSetKey),
outproxy.SetHttpLeaseSetPrivateKey(config.LeaseSetPrivateKey),
outproxy.SetHttpLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
outproxy.SetHttpAllowZeroIn(config.InAllowZeroHop),
outproxy.SetHttpAllowZeroOut(config.OutAllowZeroHop),
outproxy.SetHttpFastRecieve(config.FastRecieve),
outproxy.SetHttpCompress(config.UseCompression),
outproxy.SetHttpReduceIdle(config.ReduceIdle),
outproxy.SetHttpReduceIdleTimeMs(config.ReduceIdleTime),
outproxy.SetHttpReduceIdleQuantity(config.ReduceIdleQuantity),
outproxy.SetHttpCloseIdle(config.CloseIdle),
outproxy.SetHttpCloseIdleTimeMs(config.CloseIdleTime),
outproxy.SetHttpAccessListType(config.AccessListType),
outproxy.SetHttpAccessList(config.AccessList),
outproxy.SetHttpMessageReliability(config.MessageReliability),
outproxy.SetHttpKeyFile(config.KeyFilePath),
//outproxy.SetHttpTargetForPort443(config.TargetForPort443),
)
}
return nil, nil
}
// NewOutProxyFromConfig generates a new OutProxy from a config file
func NewHttpOutProxyFromConfig(iniFile, SamHost, SamPort string, label ...string) (*outproxy.OutProxy, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewOutProxyFromConf(config)
}
return nil, nil
}

View File

@@ -0,0 +1,194 @@
package i2ptunhelper
import (
"github.com/eyedeekay/eephttpd"
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/options"
"github.com/eyedeekay/sam-forwarder/tcp"
"github.com/eyedeekay/sam-forwarder/udp"
)
// NewSAMForwarderFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewSAMForwarderFromConf(config *i2ptunconf.Conf) (*samforwarder.SAMForwarder, error) {
if config != nil {
return samforwarder.NewSAMForwarderFromOptions(
samoptions.SetType(config.Type),
samoptions.SetSaveFile(config.SaveFile),
samoptions.SetFilePath(config.SaveDirectory),
samoptions.SetHost(config.TargetHost),
samoptions.SetPort(config.TargetPort),
samoptions.SetSAMHost(config.SamHost),
samoptions.SetSAMPort(config.SamPort),
samoptions.SetSigType(config.SigType),
samoptions.SetName(config.TunName),
samoptions.SetInLength(config.InLength),
samoptions.SetOutLength(config.OutLength),
samoptions.SetInVariance(config.InVariance),
samoptions.SetOutVariance(config.OutVariance),
samoptions.SetInQuantity(config.InQuantity),
samoptions.SetOutQuantity(config.OutQuantity),
samoptions.SetInBackups(config.InBackupQuantity),
samoptions.SetOutBackups(config.OutBackupQuantity),
samoptions.SetEncrypt(config.EncryptLeaseSet),
samoptions.SetLeaseSetKey(config.LeaseSetKey),
samoptions.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samoptions.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samoptions.SetAllowZeroIn(config.InAllowZeroHop),
samoptions.SetAllowZeroOut(config.OutAllowZeroHop),
samoptions.SetFastRecieve(config.FastRecieve),
samoptions.SetCompress(config.UseCompression),
samoptions.SetReduceIdle(config.ReduceIdle),
samoptions.SetReduceIdleTimeMs(config.ReduceIdleTime),
samoptions.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samoptions.SetCloseIdle(config.CloseIdle),
samoptions.SetCloseIdleTimeMs(config.CloseIdleTime),
samoptions.SetAccessListType(config.AccessListType),
samoptions.SetAccessList(config.AccessList),
samoptions.SetMessageReliability(config.MessageReliability),
samoptions.SetKeyFile(config.KeyFilePath),
//samoptions.SetTargetForPort443(config.TargetForPort443),
)
}
return nil, nil
}
// NewSAMForwarderFromConfig generates a new SAMForwarder from a config file
func NewSAMForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarder.SAMForwarder, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMForwarderFromConf(config)
}
return nil, nil
}
// NewSAMDGForwarderFromConf generates a SAMSSUforwarder from *i2ptunconf.Conf
func NewSAMDGForwarderFromConf(config *i2ptunconf.Conf) (*samforwarderudp.SAMDGForwarder, error) {
if config != nil {
return samforwarderudp.NewSAMDGForwarderFromOptions(
samoptions.SetSaveFile(config.SaveFile),
samoptions.SetFilePath(config.SaveDirectory),
samoptions.SetHost(config.TargetHost),
samoptions.SetPort(config.TargetPort),
samoptions.SetSAMHost(config.SamHost),
samoptions.SetSAMPort(config.SamPort),
samoptions.SetSigType(config.SigType),
samoptions.SetName(config.TunName),
samoptions.SetInLength(config.InLength),
samoptions.SetOutLength(config.OutLength),
samoptions.SetInVariance(config.InVariance),
samoptions.SetOutVariance(config.OutVariance),
samoptions.SetInQuantity(config.InQuantity),
samoptions.SetOutQuantity(config.OutQuantity),
samoptions.SetInBackups(config.InBackupQuantity),
samoptions.SetOutBackups(config.OutBackupQuantity),
samoptions.SetEncrypt(config.EncryptLeaseSet),
samoptions.SetLeaseSetKey(config.LeaseSetKey),
samoptions.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samoptions.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samoptions.SetAllowZeroIn(config.InAllowZeroHop),
samoptions.SetAllowZeroOut(config.OutAllowZeroHop),
samoptions.SetFastRecieve(config.FastRecieve),
samoptions.SetCompress(config.UseCompression),
samoptions.SetReduceIdle(config.ReduceIdle),
samoptions.SetReduceIdleTimeMs(config.ReduceIdleTime),
samoptions.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samoptions.SetCloseIdle(config.CloseIdle),
samoptions.SetCloseIdleTimeMs(config.CloseIdleTime),
samoptions.SetAccessListType(config.AccessListType),
samoptions.SetAccessList(config.AccessList),
samoptions.SetMessageReliability(config.MessageReliability),
samoptions.SetKeyFile(config.KeyFilePath),
)
}
return nil, nil
}
// NewSAMDGForwarderFromConfig generates a new SAMDGForwarder from a config file
func NewSAMDGForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarderudp.SAMDGForwarder, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewSAMDGForwarderFromConf(config)
}
return nil, nil
}
// NewEepHttpdFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewEepHttpdFromConf(config *i2ptunconf.Conf) (*eephttpd.EepHttpd, error) {
if config != nil {
return eephttpd.NewEepHttpdFromOptions(
eephttpd.SetType(config.Type),
eephttpd.SetSaveFile(config.SaveFile),
eephttpd.SetFilePath(config.SaveDirectory),
eephttpd.SetHost(config.TargetHost),
eephttpd.SetPort(config.TargetPort),
eephttpd.SetSAMHost(config.SamHost),
eephttpd.SetSAMPort(config.SamPort),
eephttpd.SetSigType(config.SigType),
eephttpd.SetName(config.TunName),
eephttpd.SetInLength(config.InLength),
eephttpd.SetOutLength(config.OutLength),
eephttpd.SetInVariance(config.InVariance),
eephttpd.SetOutVariance(config.OutVariance),
eephttpd.SetInQuantity(config.InQuantity),
eephttpd.SetOutQuantity(config.OutQuantity),
eephttpd.SetInBackups(config.InBackupQuantity),
eephttpd.SetOutBackups(config.OutBackupQuantity),
eephttpd.SetEncrypt(config.EncryptLeaseSet),
eephttpd.SetLeaseSetKey(config.LeaseSetKey),
eephttpd.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
eephttpd.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
eephttpd.SetAllowZeroIn(config.InAllowZeroHop),
eephttpd.SetAllowZeroOut(config.OutAllowZeroHop),
eephttpd.SetFastRecieve(config.FastRecieve),
eephttpd.SetCompress(config.UseCompression),
eephttpd.SetReduceIdle(config.ReduceIdle),
eephttpd.SetReduceIdleTimeMs(config.ReduceIdleTime),
eephttpd.SetReduceIdleQuantity(config.ReduceIdleQuantity),
eephttpd.SetCloseIdle(config.CloseIdle),
eephttpd.SetCloseIdleTimeMs(config.CloseIdleTime),
eephttpd.SetAccessListType(config.AccessListType),
eephttpd.SetAccessList(config.AccessList),
eephttpd.SetMessageReliability(config.MessageReliability),
eephttpd.SetKeyFile(config.KeyFilePath),
eephttpd.SetServeDir(config.ServeDirectory),
//eephttpd.SetTargetForPort443(config.TargetForPort443),
)
}
return nil, nil
}
// NewEepHttpdFromConfig generates a new EepHttpd from a config file
func NewEepHttpdFromConfig(iniFile, SamHost, SamPort string, label ...string) (*eephttpd.EepHttpd, error) {
if iniFile != "none" {
config, err := i2ptunconf.NewI2PTunConf(iniFile, label...)
if err != nil {
return nil, err
}
if SamHost != "" && SamHost != "127.0.0.1" && SamHost != "localhost" {
config.SamHost = config.GetSAMHost(SamHost, config.SamHost)
}
if SamPort != "" && SamPort != "7656" {
config.SamPort = config.GetSAMPort(SamPort, config.SamPort)
}
return NewEepHttpdFromConf(config)
}
return nil, nil
}

53
config/hostport.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetHost takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetHost(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("host", label...); o {
return x
}
return arg
}
// GetPort takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetPort(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("port", label...); o {
return x
}
return arg
}
// SetHost sets the host to forward from the config file
func (c *Conf) SetHost(label ...string) {
if v, ok := c.Get("host", label...); ok {
c.TargetHost = v
} else {
c.TargetHost = "127.0.0.1"
}
}
// SetPort sets the port to forward from the config file
func (c *Conf) SetPort(label ...string) {
if v, ok := c.Get("port", label...); ok {
c.TargetPort = v
} else {
c.TargetPort = "8081"
}
}

131
config/leasesets.go Normal file
View File

@@ -0,0 +1,131 @@
package i2ptunconf
// GetEncryptLeaseset takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetEncryptLeaseset(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("i2cp.encryptLeaseSet", label...); o {
return x
}
return arg
}
// SetEncryptLease tells the conf to use encrypted leasesets the from the config file
func (c *Conf) SetEncryptLease(label ...string) {
if v, ok := c.GetBool("i2cp.encryptLeaseSet", label...); ok {
c.EncryptLeaseSet = v
} else {
c.EncryptLeaseSet = false
}
}
// GetLeasesetKey takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetLeasesetKey(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("i2cp.leaseSetKey", label...); o {
return x
}
return arg
}
// SetEncryptLease tells the conf to use encrypted leasesets the from the config file
func (c *Conf) SetLeasesetKey(label ...string) {
if v, ok := c.Get("i2cp.leaseSetKey", label...); ok {
c.LeaseSetKey = v
} else {
c.LeaseSetKey = ""
}
}
// GetLeasesetPrivateKey takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetLeasesetPrivateKey(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("i2cp.leaseSetPrivateKey", label...); o {
return x
}
return arg
}
// SetLeasesetPrivateKey tells the conf to use encrypted leasesets the from the config file
func (c *Conf) SetLeasesetPrivateKey(label ...string) {
if v, ok := c.Get("i2cp.leaseSetPrivateKey", label...); ok {
c.LeaseSetPrivateKey = v
} else {
c.LeaseSetPrivateKey = ""
}
}
// GetLeasesetPrivateSigningKey takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetLeasesetPrivateSigningKey(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("i2cp.leaseSetPrivateSigningKey", label...); o {
return x
}
return arg
}
// SetLeasesetPrivateSigningKey tells the conf to use encrypted leasesets the from the config file
func (c *Conf) SetLeasesetPrivateSigningKey(label ...string) {
if v, ok := c.Get("i2cp.leaseSetPrivateKey", label...); ok {
c.LeaseSetPrivateSigningKey = v
} else {
c.LeaseSetPrivateSigningKey = ""
}
}
// GetLeaseSetEncType takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetLeaseSetEncType(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("i2cp.leaseSetEncType", label...); o {
return x
}
return arg
}
// SetLeaseSetEncType tells the conf to use encrypted leasesets the from the config file
func (c *Conf) SetLeaseSetEncType(label ...string) {
if v, ok := c.Get("i2cp.leaseSetEncType", label...); ok {
c.LeaseSetEncType = v
} else {
c.LeaseSetEncType = ""
}
}

53
config/length.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetInLength takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetInLength(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("inbound.length", label...); o {
return x
}
return arg
}
// GetOutLength takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetOutLength(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("outbound.length", label...); o {
return x
}
return arg
}
// SetInLength sets the inbound length from the config file
func (c *Conf) SetInLength(label ...string) {
if v, ok := c.GetInt("inbound.length", label...); ok {
c.OutLength = v
} else {
c.OutLength = 3
}
}
// SetOutLength sets the outbound lenth from the config file
func (c *Conf) SetOutLength(label ...string) {
if v, ok := c.GetInt("outbound.length", label...); ok {
c.InLength = v
} else {
c.InLength = 3
}
}

52
config/name.go Normal file
View File

@@ -0,0 +1,52 @@
package i2ptunconf
// GetSaveFile takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetSaveFile(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
return c.SaveFile
}
// GetKeys takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetKeys(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("keys", label...); o {
return x
}
return arg
}
// SetKeys sets the key name from the config file
func (c *Conf) SetKeys(label ...string) {
if v, ok := c.Get("keys", label...); ok {
c.TunName = v
c.SaveFile = true
} else {
c.TunName = "forwarder"
c.SaveFile = false
}
}
// SetTunName sets the tunnel name from the config file
func (c *Conf) SetTunName(label ...string) {
if v, ok := c.Get("keys", label...); ok {
c.TunName = v
} else {
c.TunName = "forwarder"
}
}

27
config/password.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetPassword takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetPassword(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("username", label...); o {
return x
}
return arg
}
// SetKeys sets the key name from the config file
func (c *Conf) SetPassword(label ...string) {
if v, ok := c.Get("username", label...); ok {
c.Password = v
} else {
c.Password = "samcatd"
}
}

53
config/quantity.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetInQuantity takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetInQuantity(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("inbound.quantity", label...); o {
return x
}
return arg
}
// GetOutQuantity takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetOutQuantity(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("outbound.quantity", label...); o {
return x
}
return arg
}
// SetInQuantity sets the inbound tunnel quantity from config file
func (c *Conf) SetInQuantity(label ...string) {
if v, ok := c.GetInt("inbound.quantity", label...); ok {
c.InQuantity = v
} else {
c.InQuantity = 1
}
}
// SetOutQuantity sets the outbound tunnel quantity from config file
func (c *Conf) SetOutQuantity(label ...string) {
if v, ok := c.GetInt("outbound.quantity", label...); ok {
c.OutQuantity = v
} else {
c.OutQuantity = 1
}
}

131
config/reduceclose.go Normal file
View File

@@ -0,0 +1,131 @@
package i2ptunconf
// GetReduceOnIdle takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetReduceOnIdle(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("i2cp.reduceOnIdle", label...); o {
return x
}
return arg
}
// GetReduceIdleTime takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetReduceIdleTime(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("i2cp.reduceIdleTime", label...); o {
return x
}
return arg
}
// GetReduceIdleQuantity takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetReduceIdleQuantity(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("i2cp.reduceIdleQuantity", label...); o {
return x
}
return arg
}
// GetCloseOnIdle takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetCloseOnIdle(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("i2cp.closeOnIdle", label...); o {
return x
}
return arg
}
// GetCloseIdleTime takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetCloseIdleTime(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("i2cp.closeIdleTime", label...); o {
return x
}
return arg
}
// SetReduceIdle sets the config to reduce tunnels after idle time from config file
func (c *Conf) SetReduceIdle(label ...string) {
if v, ok := c.GetBool("i2cp.reduceOnIdle", label...); ok {
c.ReduceIdle = v
} else {
c.ReduceIdle = false
}
}
// SetReduceIdleTime sets the time to wait before reducing tunnels from config file
func (c *Conf) SetReduceIdleTime(label ...string) {
if v, ok := c.GetInt("i2cp.reduceIdleTime", label...); ok {
c.ReduceIdleTime = v
} else {
c.ReduceIdleTime = 300000
}
}
// SetReduceIdleQuantity sets the number of tunnels to reduce to from config file
func (c *Conf) SetReduceIdleQuantity(label ...string) {
if v, ok := c.GetInt("i2cp.reduceQuantity", label...); ok {
c.ReduceIdleQuantity = v
} else {
c.ReduceIdleQuantity = 3
}
}
// SetCloseIdle sets the tunnel to automatically close on idle from the config file
func (c *Conf) SetCloseIdle(label ...string) {
if v, ok := c.GetBool("i2cp.closeOnIdle", label...); ok {
c.CloseIdle = v
} else {
c.CloseIdle = false
}
}
// SetCloseIdleTime sets the time to wait before killing a tunnel from a config file
func (c *Conf) SetCloseIdleTime(label ...string) {
if v, ok := c.GetInt("i2cp.closeIdleTime", label...); ok {
c.CloseIdleTime = v
} else {
c.CloseIdleTime = 300000
}
}

33
config/reliability.go Normal file
View File

@@ -0,0 +1,33 @@
package i2ptunconf
//i2cp.messageReliability
// GetMessageReliability takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetMessageReliability(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
return c.MessageReliability
}
// SetMessageReliability sets the access list type from a config file
func (c *Conf) SetMessageReliability(label ...string) {
if v, ok := c.Get("i2cp.messageReliability", label...); ok {
c.MessageReliability = v
}
if c.MessageReliability != "BestEffort" && c.MessageReliability != "none" {
c.MessageReliability = "none"
}
}
func (c *Conf) reliability() string {
if c.MessageReliability != "" {
return "i2cp.messageReliability=" + c.MessageReliability
}
return ""
}

53
config/samhostport.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetSAMHost takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetSAMHost(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("samhost", label...); o {
return x
}
return arg
}
// GetSAMPort takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetSAMPort(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("samport", label...); o {
return x
}
return arg
}
// SetSAMHost sets the SAM host from the config file
func (c *Conf) SetSAMHost(label ...string) {
if v, ok := c.Get("samhost", label...); ok {
c.SamHost = v
} else {
c.SamHost = "127.0.0.1"
}
}
// SetSAMPort sets the SAM port from the config file
func (c *Conf) SetSAMPort(label ...string) {
if v, ok := c.Get("samport", label...); ok {
c.SamPort = v
} else {
c.SamPort = "7656"
}
}

45
config/sigtype.go Normal file
View File

@@ -0,0 +1,45 @@
package i2ptunconf
// GetSigType takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetSigType(argt, def string, label ...string) string {
var typ string
if argt == "" {
typ = ""
} else if argt == "DSA_SHA1" {
typ = "DSA_SHA1"
} else if argt == "ECDSA_SHA256_P256" {
typ = "ECDSA_SHA256_P256"
} else if argt == "ECDSA_SHA384_P384" {
typ = "ECDSA_SHA384_P384"
} else if argt == "ECDSA_SHA512_P521" {
typ = "ECDSA_SHA512_P521"
} else if argt == "EdDSA_SHA512_Ed25519" {
typ = "EdDSA_SHA512_Ed25519"
} else {
typ = "EdDSA_SHA512_Ed25519"
}
if typ != def {
return typ
}
if c.Config == nil {
return typ
}
if x, o := c.Get("signaturetype", label...); o {
return x
}
return def
}
// SetSigType sets the type of proxy to create from the config file
func (c *Conf) SetSigType(label ...string) {
if v, ok := c.Get("signaturetype", label...); ok {
if c.SigType == "" || c.SigType == "DSA_SHA1" || c.SigType == "ECDSA_SHA256_P256" || c.SigType == "ECDSA_SHA384_P384" || c.SigType == "ECDSA_SHA512_P521" || c.SigType == "EdDSA_SHA512_Ed25519" {
c.SigType = v
}
} else {
c.SigType = "EdDSA_SHA512_Ed25519"
}
}

1
config/timeout.go Normal file
View File

@@ -0,0 +1 @@
package i2ptunconf

111
config/tls.go Normal file
View File

@@ -0,0 +1,111 @@
package i2ptunconf
import (
"crypto/tls"
"strings"
"github.com/eyedeekay/sam-forwarder/tls"
)
// GetPort443 takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetPort443(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("targetForPort.443", label...); o {
return x
}
return arg
}
// SetTargetPort443 sets the port to forward from the config file
func (c *Conf) SetTargetPort443(label ...string) {
if v, ok := c.Get("targetForPort.443", label...); ok {
c.TargetForPort443 = v
} else {
c.TargetForPort443 = ""
}
}
// Get
func (c *Conf) GetUseTLS(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("usetls", label...); o {
return x
}
return arg
}
// SetAllowZeroHopOut sets the config to allow zero-hop tunnels
func (c *Conf) SetUseTLS(label ...string) {
if v, ok := c.GetBool("usetls", label...); ok {
c.UseTLS = v
} else {
c.UseTLS = false
}
}
// GetTLSConfig
func (c *Conf) GetTLSConfigCertPem(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("cert.pem", label...); o {
return x
}
return arg
}
// SetClientDest sets the key name from the config file
func (c *Conf) SetTLSConfigCertPem(label ...string) {
if v, ok := c.Get("cert.pem", label...); ok {
c.Cert = v
} else {
c.Cert = ""
}
}
// GetTLSConfig
func (c *Conf) GetTLSConfigKeyPem(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("key.pem", label...); o {
return x
}
return arg
}
// SetClientDest sets the key name from the config file
func (c *Conf) SetTLSConfigKeyPem(label ...string) {
if v, ok := c.Get("key.pem", label...); ok {
c.Pem = v
} else {
c.Pem = ""
}
}
func (c *Conf) TLSConfig() (*tls.Config, error) {
names := []string{c.Base32()}
if c.HostName != "" && strings.HasSuffix(c.HostName, ".i2p") {
names = append(names, c.HostName)
}
return i2ptls.TLSConfig(c.Cert, c.Pem, names)
}

File diff suppressed because it is too large Load Diff

119
config/type.go Normal file
View File

@@ -0,0 +1,119 @@
package i2ptunconf
import (
"strings"
)
// GetType takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetTypes(argc, argu, argh bool, def string, label ...string) string {
var typ string
if argu {
typ += "udp"
}
if argc {
if argh == true {
typ += "http"
}
typ += "client"
c.Client = true
} else {
if argh == true {
typ += "http"
} else {
typ += "server"
}
if typ != def {
return typ
}
}
if def == "kcpclient" {
return def
}
if def == "kcpserver" {
return def
}
if def == "eephttpd" {
return def
}
if def == "vpnclient" {
return def
}
if def == "vpnserver" {
return def
}
if def == "outproxy" {
return def
}
if def == "outproxyhttp" {
return def
}
if def == "browserclient" {
return def
}
if c.Config == nil {
return typ
}
if x, o := c.Get("type", label...); o {
return x
}
return def
}
func (c *Conf) GetOtherType(typ, def string, label ...string) string {
if typ != def {
return typ
}
if c.Config == nil {
return typ
}
if x, o := c.Get("type", label...); o {
return x
}
return def
}
// SetType sets the type of proxy to create from the config file
func (c *Conf) SetType(label ...string) {
if v, ok := c.Get("type", label...); ok {
if strings.Contains(v, "client") {
c.Client = true
}
switch c.Type {
case "server":
c.Type = v
case "http":
c.Type = v
case "client":
c.Type = v
case "httpclient":
c.Type = v
case "browserclient":
c.Type = v
case "udpserver":
c.Type = v
case "udpclient":
c.Type = v
case "eephttpd":
c.Type = v
case "outproxy":
c.Type = v
case "outproxyhttp":
c.Type = v
case "vpnserver":
c.Type = v
case "vpnclient":
c.Type = v
case "kcpclient":
c.Type = v
case "kcpserver":
c.Type = v
default:
c.Type = "browserclient"
}
} else {
c.Type = "browserclient"
}
}

27
config/user.go Normal file
View File

@@ -0,0 +1,27 @@
package i2ptunconf
// GetUserName takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetUserName(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("username", label...); o {
return x
}
return arg
}
// SetKeys sets the key name from the config file
func (c *Conf) SetUserName(label ...string) {
if v, ok := c.Get("username", label...); ok {
c.UserName = v
} else {
c.UserName = "samcatd"
}
}

53
config/variance.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetInVariance takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetInVariance(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("inbound.variance", label...); o {
return x
}
return arg
}
// GetOutVariance takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetOutVariance(arg, def int, label ...string) int {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetInt("outbound.variance", label...); o {
return x
}
return arg
}
// SetInVariance sets the inbound tunnel variance from config file
func (c *Conf) SetInVariance(label ...string) {
if v, ok := c.GetInt("inbound.variance", label...); ok {
c.InVariance = v
} else {
c.InVariance = 0
}
}
// SetOutVariance sets the outbound tunnel variance from config file
func (c *Conf) SetOutVariance(label ...string) {
if v, ok := c.GetInt("outbound.variance", label...); ok {
c.OutVariance = v
} else {
c.OutVariance = 0
}
}

29
config/wwwdir.go Normal file
View File

@@ -0,0 +1,29 @@
package i2ptunconf
//
// GetDir takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetWWWDir(arg, def string, label ...string) string {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.Get("wwwdir", label...); o {
return x
}
return arg
}
// SetDir sets the key save directory from the config file
func (c *Conf) SetWWWDir(label ...string) {
if v, ok := c.Get("wwwdir", label...); ok {
c.ServeDirectory = v
} else {
c.ServeDirectory = "./www"
}
}

53
config/zerohops.go Normal file
View File

@@ -0,0 +1,53 @@
package i2ptunconf
// GetInAllowZeroHop takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetInAllowZeroHop(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("inbound.allowZeroHop", label...); o {
return x
}
return arg
}
// GetOutAllowZeroHop takes an argument and a default. If the argument differs from the
// default, the argument is always returned. If the argument and default are
// the same and the key exists, the key is returned. If the key is absent, the
// default is returned.
func (c *Conf) GetOutAllowZeroHop(arg, def bool, label ...string) bool {
if arg != def {
return arg
}
if c.Config == nil {
return arg
}
if x, o := c.GetBool("outbound.allowZeroHop", label...); o {
return x
}
return arg
}
// SetAllowZeroHopIn sets the config to allow zero-hop tunnels
func (c *Conf) SetAllowZeroHopIn(label ...string) {
if v, ok := c.GetBool("inbound.allowZeroHop", label...); ok {
c.InAllowZeroHop = v
} else {
c.InAllowZeroHop = false
}
}
// SetAllowZeroHopOut sets the config to allow zero-hop tunnels
func (c *Conf) SetAllowZeroHopOut(label ...string) {
if v, ok := c.GetBool("outbound.allowZeroHop", label...); ok {
c.OutAllowZeroHop = v
} else {
c.OutAllowZeroHop = false
}
}

78
docs/EMBEDDING.md Normal file
View File

@@ -0,0 +1,78 @@
Embedding i2p support in your Go application with samforwarder
==============================================================
One neat thing you can do with samforwarder is make eepWeb(?) services configure
themselves automatically by adding it to an existing Go application. To help
with this process, the samforwarder/config/ file has a bunch of helper
functions and a class for parsing configuration files directly. You can import
it, add a few flags(or however you configure your service) and fire off the
forwarder as a goroutne, all you have to do is configure it to forward the port
used by your service. This makes it extremely easy to do, but it should only be
used in this way for applications that would already be safe to host as services
in i2p or other overlay networks. In particular, it should only be used for
applications that don't require extensive login information and do not leak
information at the application layer.
So without further ado, a blatant copy-paste of information that shouldn't have
been in the README.md.
## Static eepsite in like no seconds
Using this port forwarder, it's possible to create an instant eepsite from a
folder full of html files(and the resources they call upon). Probably obviously
to everybody reading this right now, but maybe not obviously to everyone reading
this forever. An example of an application that works this way is available
[here at my eephttpd repo](https://github.com/eyedeekay/eephttpd).
## Quick-And-Dirty i2p-enabled golang web applications
Normal web applications can easily add the ability to serve itself over i2p by
importing and configuring this forwarding doodad. Wherever it takes the argument
for the web server's listening host and/or port, pass that same host and/or port
to a new instance of the "SAMForwarder" and then run the "Serve" function of the
SAMForwarder as a goroutine. This simply forwards the running service to the i2p
network, it doesn't do any filtering, and if your application establishes
out-of-band connections, those may escape. Also, if your application is
listening on all addresses, it will be visible from the local network.
Here's a simple example with a simple static file server:
```Diff
package main package main
import ( import (
"flag" "flag"
"log" "log"
"net/http" "net/http"
) )
> import "github.com/eyedeekay/sam-forwarder"
>
func main() { func main() {
port := flag.String("p", "8100", "port to serve on") port := flag.String("p", "8100", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host") directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse() flag.Parse()
>
> forwarder, err := samforwarder.NewSAMForwarderFromOptions(
> samforwarder.SetHost("127.0.0.1"),
> samforwarder.SetPort(*port),
> samforwarder.SetSAMHost("127.0.0.1"),
> samforwarder.SetSAMPort("7656"),
> samforwarder.SetName("staticfiles"),
> )
> if err != nil {
> log.Fatal(err.Error())
> }
> go forwarder.Serve()
http.Handle("/", http.FileServer(http.Dir(*directory))) http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port) log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil)) log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil))
} }
```
[This tiny file server taken from here and used for this example](https://gist.github.com/paulmach/7271283)
## Integrating your Go web application with i2p using sam-forwarder

3
docs/PACKAGECONF.md Normal file
View File

@@ -0,0 +1,3 @@
Encapsulating and Packaging Application Configuration with samcatd
==================================================================

225
docs/USAGE.md Normal file
View File

@@ -0,0 +1,225 @@
samcatd - Router-independent tunnel management for i2p
=========================================================
samcatd is a daemon which runs a group of forwarding proxies to
provide services over i2p independent of the router. It also serves
as a generalized i2p networking utility for power-users. It's
intended to be a Swiss-army knife for the SAM API.
usage:
------
```
flag needs an argument: -h
Usage of ./bin/samcatd:
-a string
Type of access list to use, can be "allowlist" "blocklist" or "none". (default "none")
-c Client proxy mode(true or false)
-conv string
Display the base32 and base64 values of a specified .i2pkeys file
-cr string
Encrypt/decrypt the key files with a passfile
-css string
custom CSS for web interface (default "css/styles.css")
-ct int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-d string
Directory to save tunnel configuration file in.
-de string
Destination to connect client's to by default.
-f string
Use an ini file for configuration(config file options override passed arguments for now.) (default "none")
-h string
Target host(Host of service to forward to i2p) (default "127.0.0.1")
-i string
Destination for client tunnels. Ignored for service tunnels. (default "none")
-ib int
Set inbound tunnel backup quantity(0 to 5) (default 2)
-ih
Inject X-I2P-DEST headers
-il int
Set inbound tunnel length(0 to 7) (default 3)
-iq int
Set inbound tunnel quantity(0 to 15) (default 6)
-iv int
Set inbound tunnel length variance(-7 to 7)
-js string
custom JS for web interface (default "js/scripts.js")
-k string
key for encrypted leaseset (default "none")
-l Use an encrypted leaseset(true or false) (default true)
-littleboss string
instruct the littleboss:
start: start and manage this process using service name "service-name"
stop: signal the littleboss to shutdown the process
status: print statistics about the running littleboss
reload: restart the managed process using the executed binary
bypass: disable littleboss, run the program directly (default "bypass")
-n string
Tunnel name, this must be unique but can be anything. (default "forwarder")
-ob int
Set outbound tunnel backup quantity(0 to 5) (default 2)
-ol int
Set outbound tunnel length(0 to 7) (default 3)
-oq int
Set outbound tunnel quantity(0 to 15) (default 6)
-ov int
Set outbound tunnel length variance(-7 to 7)
-p string
Target port(Port of service to forward to i2p) (default "8081")
-pk string
private key for encrypted leaseset (default "none")
-psk string
private signing key for encrypted leaseset (default "none")
-r Reduce tunnel quantity when idle(true or false)
-rq int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-rt int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-s Start a tunnel with the passed parameters(Otherwise, they will be treated as default values.)
-sh string
SAM host (default "127.0.0.1")
-sp string
SAM port (default "7656")
-st string
Signature type
-t Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.
-tls string
(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)
-u UDP mode(true or false)
-w Start web administration interface
-wp string
Web port (default "7957")
-x Close tunnel idle(true or false)
-z Uze gzip(true or false)
-zi
Allow zero-hop, non-anonymous tunnels in(true or false)
-zo
Allow zero-hop, non-anonymous tunnels out(true or false)
```
managing samcatd save-encryption keys
=====================================
In order to keep from saving the .i2pkeys files in plaintext format, samcatd
can optionally generate a key and encrypt the .i2pkeys files securely. Of
course, to fully benefit from this arrangement, you need to move those keys
away from the machine where the tunnel keys(the .i2pkeys file) are located,
or protect them in some other way(sandboxing, etc). If you want to use
encrypted .i2pkeys files, you can specify a key file to use with the -cr
option on the terminal or with keyfile option in the .ini file.
example config - valid for both ephsite and samcat
==================================================
Options are still being added, pretty much as fast as I can put them
in. For up-to-the-minute options, see [the checklist](config/CHECKLIST.md)
(**ephsite** will only use top-level options, but they can be labeled or
unlabeled)
(**samcatd** treats the first set of options it sees as the default, and
does not start tunnels based on unlabeled options unless passed the
-s flag.)
``` ini
## Defaults, these are only invoked with the -start option or if labeled tunnels
## are not present(samcatd instructions). **THESE** are the correct config files
## to use as defaults, and not the ones in ../sam-forwarder/tunnels.ini, which
## are used for testing settings availability only.
inbound.length = 3
outbound.length = 3
inbound.lengthVariance = 0
outbound.lengthVariance = 0
inbound.backupQuantity = 3
outbound.backupQuantity = 3
inbound.quantity = 5
outbound.quantity = 5
inbound.allowZeroHop = false
outbound.allowZeroHop = false
i2cp.encryptLeaseSet = false
gzip = true
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 2
i2cp.enableWhiteList = false
i2cp.enableBlackList = false
keyfile = "/usr/share/samcatd/samcatd"
#[sam-forwarder-tcp-server]
#type = server
#host = 127.0.0.1
#port = 8081
#inbound.length = 3
#outbound.length = 3
#keys = forwarder
[sam-forwarder-tcp-client]
type = client
host = 127.0.0.1
port = 8082
inbound.length = 3
outbound.length = 3
destination = i2p-projekt.i2p
keys = forwarder-two
#[sam-forwarder-udp-server]
#type = udpserver
#host = 127.0.0.1
#port = 8084
#inbound.length = 6
#outbound.length = 3
#keys = forwarder-four
#[sam-forwarder-udp-client]
#type = udpclient
#host = 127.0.0.1
#port = 8083
#inbound.length = 3
#outbound.length = 3
#destination = i2p-projekt.i2p
#keys = forwarder-three
#[sam-forwarder-tcp-http-server]
#type = http
#host = 127.0.0.1
#port = 8085
#inbound.length = 3
#outbound.length = 3
#keys = forwarder-five
#[sam-forwarder-vpn-server]
#type = udpserver
#host = 127.0.0.1
#port = 8084
#inbound.length = 2
#outbound.length = 2
#inbound.backupQuantity = 3
#outbound.backupQuantity = 3
#inbound.quantity = 5
#outbound.quantity = 5
#i2cp.reduceOnIdle = true
#i2cp.reduceIdleTime = 3000000
#i2cp.reduceQuantity = 2
#i2cp.closeOnIdle = false
#keys = i2pvpnserver
#[sam-forwarder-vpn-client]
#type = udpclient
#host = 127.0.0.1
#port = 8085
#inbound.length = 2
#outbound.length = 2
#inbound.backupQuantity = 3
#outbound.backupQuantity = 3
#inbound.quantity = 5
#outbound.quantity = 5
#i2cp.reduceOnIdle = true
#i2cp.reduceIdleTime = 3000000
#i2cp.reduceQuantity = 2
#destination = adestinationisrequiredorbespecifiedatruntime.i2p
#keys = i2pvpnclient
```

96
docs/checklist.html Normal file
View File

@@ -0,0 +1,96 @@
<h1 id="i2cptunnel-options-implementation-checklist">I2CP/Tunnel Options Implementation Checklist</h1>
<p>This version of this document is valid for sam-forwarder. If youd like to use it, the original is at <a href="CHECKLIST.orig.md" class="uri">CHECKLIST.orig.md</a>.</p>
<p>key:</p>
<pre><code>- \[U\] - Undone/Unknown
- \[C\] - Confirmed Working
- \[W\] - Work in progress
- \[N\] - Not applicable/Won&#39;t be implemented without good reason.
- \[*\] - See also
Version Recommended Allowable Default
[U] - clientMessageTimeout 8*1000 - 120*1000 60*1000 The timeout (ms) for all sent messages. Unused. See the protocol specification for per-message settings.
[N] - crypto.lowTagThreshold 0.9.2 1-128 30 Minimum number of ElGamal/AES Session Tags before we send more. Recommended: approximately tagsToSend * 2/3
[N] - crypto.tagsToSend 0.9.2 1-128 40 Number of ElGamal/AES Session Tags to send at a time. For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
[U] - explicitPeers null Comma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
[C] - i2cp.dontPublishLeaseSet true,false false Should generally be set to true for clients and false for servers
[C] - i2cp.fastReceive 0.9.4 true,false false If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.messageReliability BestEffort, None BestEffort Guaranteed is disabled; None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
[U] - i2cp.password 0.8.2 string For authorization, if required by the router. If the client is running in the same JVM as a router, this option is not required. Warning - username and password are sent in the clear to the router, unless using SSL (i2cp.SSL=true). Authorization is only recommended when using SSL.
[U] - i2cp.username 0.8.2 string
[C] - inbound.allowZeroHop true,false true If incoming zero hop tunnel is allowed
[C] - outbound.allowZeroHop true,false true If outgoing zero hop tunnel is allowed
[C] - inbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels in
[C] - outbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels out
[U] - inbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[U] - outbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[C] - inbound.length 0 to 3 0 to 7 3 Length of tunnels in
[C] - outbound.length 0 to 3 0 to 7 3 Length of tunnels out
[C] - inbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels in. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[C] - outbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels out. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[U] - inbound.nickname string Name of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
[U] - outbound.nickname string Name of tunnel - generally ignored unless inbound.nickname is unset.
[U] - outbound.priority 0.9.4 -25 to 25 -25 to 25 0 Priority adjustment for outbound messages. Higher is higher priority.
[C] - inbound.quantity 1 to 3 1 to 16 2 Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are incompatible with older releases.
[C] - outbound.quantity 1 to 3 No limit 2 Number of tunnels out
[U] - inbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[U] - outbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[*] - inbound.* Any other options prefixed with &quot;inbound.&quot; are stored in the &quot;unknown options&quot; properties of the inbound tunnel pool&#39;s settings.
[*] - outbound.* Any other options prefixed with &quot;outbound.&quot; are stored in the &quot;unknown options&quot; properties of the outbound tunnel pool&#39;s settings.
[U] - shouldBundleReplyInfo 0.9.2 true,false true Set to false to disable ever bundling a reply LeaseSet. For clients that do not publish their LeaseSet, this option must be true for any reply to be possible. &quot;true&quot; is also recommended for multihomed servers with long connection times. Setting to &quot;false&quot; may save significant outbound bandwidth, especially if the client is configured with a large number of inbound tunnels (Leases). If replies are still required, this may shift the bandwidth burden to the far-end client and the floodfill. There are several cases where &quot;false&quot; may be appropriate: Unidirectional communication, no reply required LeaseSet is published and higher reply latency is acceptable LeaseSet is published, client is a &quot;server&quot;, all connections are inbound so the connecting far-end destination obviously has the leaseset already. Connections are either short, or it is acceptable for latency on a long-lived connection to temporarily increase while the other end re-fetches the LeaseSet after expiration. HTTP servers may fit these requirements.
[C] - i2cp.closeIdleTime 0.7.1 1800000 300000 minimum (ms) Idle time required (default 30 minutes)
[C] - i2cp.closeOnIdle 0.7.1 true,false false Close I2P session when idle
[C] - i2cp.encryptLeaseSet 0.7.1 true,false false Encrypt the lease
[C] - i2cp.fastReceive 0.9.4 true,false true If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.gzip 0.6.5 true,false true Gzip outbound data
[C] - i2cp.leaseSetKey 0.7.1 For encrypted leasesets. Base 64 SessionKey (44 characters)
[C] - i2cp.leaseSetPrivateKey 0.9.18 Base 64 private key for encryption. Optionally preceded by the key type and &#39;:&#39;. Only &quot;ELGAMAL_2048:&quot; is supported, which is the default. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.leaseSetSigningPrivateKey 0.9.18 Base 64 private key for signatures. Optionally preceded by the key type and &#39;:&#39;. DSA_SHA1 is the default. Key type must match the signature type in the destination. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.reduceIdleTime 0.7.1 1200000 300000 minimum (ms) Idle time required (default 20 minutes, minimum 5 minutes)
[C] - i2cp.reduceOnIdle 0.7.1 true,false false Reduce tunnel quantity when idle
[C] - i2cp.reduceQuantity 0.7.1 1 1 to 5 1 Tunnel quantity when reduced (applies to both inbound and outbound)
[*] - i2cp.SSL 0.8.3 true,false false Connect to the router using SSL. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.host 127.0.0.1 Router hostname. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.port 1-65535 7654 Router I2CP port. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
Default Description
[C] - i2cp.accessList null Comma- or space-separated list of Base64 peer Hashes used for either access list or blocklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a allowlist for incoming connections. The name or number of the signature type for a transient destination. As of release 0.9.12.
[C] - i2cp.enableAccessList false Use the access list as a allowlist for incoming connections. As of release 0.7.13.
[C] - i2cp.enableBlackList false Use the access list as a blocklist for incoming connections. As of release 0.7.13.
[U] - i2p.streaming.answerPings true Whether to respond to incoming pings
[U] - i2p.streaming.blocklist null Comma- or space-separated list of Base64 peer Hashes to be blocklisted for incoming connections to ALL destinations in the context. This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.3.
[U] - i2p.streaming.bufferSize 64K How much transmit data (in bytes) will be accepted that hasn&#39;t been written out yet.
[U] - i2p.streaming.congestionAvoidanceGrowthRateFactor 1 When we&#39;re in congestion avoidance, we grow the window size at the rate of 1/(windowSize*factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.connectDelay -1 How long to wait after instantiating a new con before actually attempting to connect. If this is &lt;= 0, connect immediately with no initial data. If greater than 0, wait until the output stream is flushed, the buffer fills, or that many milliseconds pass, and include any initial data with the SYN.
[U] - i2p.streaming.connectTimeout 5*60*1000 How long to block on connect, in milliseconds. Negative means indefinitely. Default is 5 minutes.
[U] - i2p.streaming.disableRejectLogging false Whether to disable warnings in the logs when an incoming connection is rejected due to connection limits. As of release 0.9.4.
[U] - i2p.streaming.dsalist null Comma- or space-separated list of Base64 peer Hashes or host names to be contacted using an alternate DSA destination. Only applies if multisession is enabled and the primary session is non-DSA (generally for shared clients only). This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.21.
[U] - i2p.streaming.enforceProtocol true Whether to listen only for the streaming protocol. Setting to true will prohibit communication with Destinations earlier than release 0.7.1 (released March 2009). Set to true if running multiple protocols on this Destination. As of release 0.9.1. Default true as of release 0.9.36.
[U] - i2p.streaming.inactivityAction 2 (send) (0=noop, 1=disconnect) What to do on an inactivity timeout - do nothing, disconnect, or send a duplicate ack.
[U] - i2p.streaming.inactivityTimeout 90*1000 Idle time before sending a keepalive
[U] - i2p.streaming.initialAckDelay 750 Delay before sending an ack
[U] - i2p.streaming.initialResendDelay 1000 The initial value of the resend delay field in the packet header, times 1000. Not fully implemented; see below.
[U] - i2p.streaming.initialRTO 9000 Initial timeout (if no sharing data available). As of release 0.9.8.
[U] - i2p.streaming.initialRTT 8000 Initial round trip time estimate (if no sharing data available). Disabled as of release 0.9.8; uses actual RTT.
[U] - i2p.streaming.initialWindowSize 6 (if no sharing data available) In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages.
[U] - i2p.streaming.limitAction reset What action to take when an incoming connection exceeds limits. Valid values are: reset (reset the connection); drop (drop the connection); or http (send a hardcoded HTTP 429 response). Any other value is a custom response to be sent. backslash-r and backslash-n will be replaced with CR and LF. As of release 0.9.34.
[U] - i2p.streaming.maxConcurrentStreams -1 (0 or negative value means unlimited) This is a total limit for incoming and outgoing combined.
[U] - i2p.streaming.maxConnsPerMinute 0 Incoming connection limit (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerHour 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerDay 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxMessageSize 1730 The MTU in bytes.
[U] - i2p.streaming.maxResends 8 Maximum number of retransmissions before failure.
[U] - i2p.streaming.maxTotalConnsPerMinute 0 Incoming connection limit (all peers; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerHour 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerDay 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxWindowSize 128
[U] - i2p.streaming.profile 1 (bulk) (2=interactive not supported) This doesn&#39;t currently do anything, but setting it to a value other than 1 will cause an error.
[U] - i2p.streaming.readTimeout -1 How long to block on read, in milliseconds. Negative means indefinitely.
[U] - i2p.streaming.slowStartGrowthRateFactor 1 When we&#39;re in slow start, we grow the window size at the rate of 1/(factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.tcbcache.rttDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.rttdevDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.wdwDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.writeTimeout -1 How long to block on write/flush, in milliseconds. Negative means indefinitely.
[C] - destination useful to consider adding to custom applications for client ocnfiguration</code></pre>
<p>* : Id like to have something like this setting internal to samcatd, but it might not always be relevant to pass it through to the real i2p router. Right now, Im leaning toward a samcatd specific setting, but maybe just alter the behavior of this setting for use with samcatd instead? Probably just give samcatd its own thing.</p>

107
docs/config/CHECKLIST.md Normal file
View File

@@ -0,0 +1,107 @@
I2CP/Tunnel Options Implementation Checklist
============================================
This version of this document is valid for sam-forwarder. If you'd like to use
it, the original is at [CHECKLIST.orig.md](CHECKLIST.orig.md).
key:
- \[U\] - Undone/Unknown
- \[C\] - Confirmed Working
- \[W\] - Work in progress
- \[N\] - Not applicable/Won't be implemented without good reason.
- \[*\] - See also
Version Recommended Allowable Default
[U] - clientMessageTimeout 8*1000 - 120*1000 60*1000 The timeout (ms) for all sent messages. Unused. See the protocol specification for per-message settings.
[N] - crypto.lowTagThreshold 0.9.2 1-128 30 Minimum number of ElGamal/AES Session Tags before we send more. Recommended: approximately tagsToSend * 2/3
[N] - crypto.tagsToSend 0.9.2 1-128 40 Number of ElGamal/AES Session Tags to send at a time. For clients with relatively low bandwidth per-client-pair (IRC, some UDP apps), this may be set lower.
[U] - explicitPeers null Comma-separated list of Base 64 Hashes of peers to build tunnels through; for debugging only
[C] - i2cp.dontPublishLeaseSet true,false false Should generally be set to true for clients and false for servers
[C] - i2cp.fastReceive 0.9.4 true,false false If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.messageReliability BestEffort, None BestEffort Guaranteed is disabled; None implemented in 0.8.1; the streaming lib default is None as of 0.8.1, the client side default is None as of 0.9.4
[U] - i2cp.password 0.8.2 string For authorization, if required by the router. If the client is running in the same JVM as a router, this option is not required. Warning - username and password are sent in the clear to the router, unless using SSL (i2cp.SSL=true). Authorization is only recommended when using SSL.
[U] - i2cp.username 0.8.2 string
[C] - inbound.allowZeroHop true,false true If incoming zero hop tunnel is allowed
[C] - outbound.allowZeroHop true,false true If outgoing zero hop tunnel is allowed
[C] - inbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels in
[C] - outbound.backupQuantity 0 to 3 No limit 0 Number of redundant fail-over for tunnels out
[U] - inbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[U] - outbound.IPRestriction 0 to 4 0 to 4 2 Number of IP bytes to match to determine if two routers should not be in the same tunnel. 0 to disable.
[C] - inbound.length 0 to 3 0 to 7 3 Length of tunnels in
[C] - outbound.length 0 to 3 0 to 7 3 Length of tunnels out
[C] - inbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels in. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[C] - outbound.lengthVariance -1 to 2 -7 to 7 0 Random amount to add or subtract to the length of tunnels out. A positive number x means add a random amount from 0 to x inclusive. A negative number -x means add a random amount from -x to x inclusive. The router will limit the total length of the tunnel to 0 to 7 inclusive. The default variance was 1 prior to release 0.7.6.
[U] - inbound.nickname string Name of tunnel - generally used in routerconsole, which will use the first few characters of the Base64 hash of the destination by default.
[U] - outbound.nickname string Name of tunnel - generally ignored unless inbound.nickname is unset.
[U] - outbound.priority 0.9.4 -25 to 25 -25 to 25 0 Priority adjustment for outbound messages. Higher is higher priority.
[C] - inbound.quantity 1 to 3 1 to 16 2 Number of tunnels in. Limit was increased from 6 to 16 in release 0.9; however, numbers higher than 6 are incompatible with older releases.
[C] - outbound.quantity 1 to 3 No limit 2 Number of tunnels out
[U] - inbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[U] - outbound.randomKey 0.9.17 Base 64 encoding of 32 random bytes Used for consistent peer ordering across restarts.
[*] - inbound.* Any other options prefixed with "inbound." are stored in the "unknown options" properties of the inbound tunnel pool's settings.
[*] - outbound.* Any other options prefixed with "outbound." are stored in the "unknown options" properties of the outbound tunnel pool's settings.
[U] - shouldBundleReplyInfo 0.9.2 true,false true Set to false to disable ever bundling a reply LeaseSet. For clients that do not publish their LeaseSet, this option must be true for any reply to be possible. "true" is also recommended for multihomed servers with long connection times. Setting to "false" may save significant outbound bandwidth, especially if the client is configured with a large number of inbound tunnels (Leases). If replies are still required, this may shift the bandwidth burden to the far-end client and the floodfill. There are several cases where "false" may be appropriate: Unidirectional communication, no reply required LeaseSet is published and higher reply latency is acceptable LeaseSet is published, client is a "server", all connections are inbound so the connecting far-end destination obviously has the leaseset already. Connections are either short, or it is acceptable for latency on a long-lived connection to temporarily increase while the other end re-fetches the LeaseSet after expiration. HTTP servers may fit these requirements.
[C] - i2cp.closeIdleTime 0.7.1 1800000 300000 minimum (ms) Idle time required (default 30 minutes)
[C] - i2cp.closeOnIdle 0.7.1 true,false false Close I2P session when idle
[C] - i2cp.encryptLeaseSet 0.7.1 true,false false Encrypt the lease
[C] - i2cp.fastReceive 0.9.4 true,false true If true, the router just sends the MessagePayload instead of sending a MessageStatus and awaiting a ReceiveMessageBegin.
[C] - i2cp.gzip 0.6.5 true,false true Gzip outbound data
[C] - i2cp.leaseSetKey 0.7.1 For encrypted leasesets. Base 64 SessionKey (44 characters)
[C] - i2cp.leaseSetPrivateKey 0.9.18 Base 64 private key for encryption. Optionally preceded by the key type and ':'. Only "ELGAMAL_2048:" is supported, which is the default. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.leaseSetSigningPrivateKey 0.9.18 Base 64 private key for signatures. Optionally preceded by the key type and ':'. DSA_SHA1 is the default. Key type must match the signature type in the destination. I2CP will generate the public key from the private key. Use for persistent leaseset keys across restarts.
[C] - i2cp.reduceIdleTime 0.7.1 1200000 300000 minimum (ms) Idle time required (default 20 minutes, minimum 5 minutes)
[C] - i2cp.reduceOnIdle 0.7.1 true,false false Reduce tunnel quantity when idle
[C] - i2cp.reduceQuantity 0.7.1 1 1 to 5 1 Tunnel quantity when reduced (applies to both inbound and outbound)
[*] - i2cp.SSL 0.8.3 true,false false Connect to the router using SSL. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.host 127.0.0.1 Router hostname. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
[*] - i2cp.tcp.port 1-65535 7654 Router I2CP port. If the client is running in the same JVM as a router, this option is ignored, and the client connects to that router internally.
Default Description
[C] - i2cp.accessList null Comma- or space-separated list of Base64 peer Hashes used for either access list or blocklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a allowlist for incoming connections. The name or number of the signature type for a transient destination. As of release 0.9.12.
[C] - i2cp.enableAccessList false Use the access list as a allowlist for incoming connections. As of release 0.7.13.
[C] - i2cp.enableBlackList false Use the access list as a blocklist for incoming connections. As of release 0.7.13.
[U] - i2p.streaming.answerPings true Whether to respond to incoming pings
[U] - i2p.streaming.blocklist null Comma- or space-separated list of Base64 peer Hashes to be blocklisted for incoming connections to ALL destinations in the context. This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.3.
[U] - i2p.streaming.bufferSize 64K How much transmit data (in bytes) will be accepted that hasn't been written out yet.
[U] - i2p.streaming.congestionAvoidanceGrowthRateFactor 1 When we're in congestion avoidance, we grow the window size at the rate of 1/(windowSize*factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.connectDelay -1 How long to wait after instantiating a new con before actually attempting to connect. If this is <= 0, connect immediately with no initial data. If greater than 0, wait until the output stream is flushed, the buffer fills, or that many milliseconds pass, and include any initial data with the SYN.
[U] - i2p.streaming.connectTimeout 5*60*1000 How long to block on connect, in milliseconds. Negative means indefinitely. Default is 5 minutes.
[U] - i2p.streaming.disableRejectLogging false Whether to disable warnings in the logs when an incoming connection is rejected due to connection limits. As of release 0.9.4.
[U] - i2p.streaming.dsalist null Comma- or space-separated list of Base64 peer Hashes or host names to be contacted using an alternate DSA destination. Only applies if multisession is enabled and the primary session is non-DSA (generally for shared clients only). This option must be set in the context properties, NOT in the createManager() options argument. Note that setting this in the router context will not affect clients outside the router in a separate JVM and context. As of release 0.9.21.
[U] - i2p.streaming.enforceProtocol true Whether to listen only for the streaming protocol. Setting to true will prohibit communication with Destinations earlier than release 0.7.1 (released March 2009). Set to true if running multiple protocols on this Destination. As of release 0.9.1. Default true as of release 0.9.36.
[U] - i2p.streaming.inactivityAction 2 (send) (0=noop, 1=disconnect) What to do on an inactivity timeout - do nothing, disconnect, or send a duplicate ack.
[U] - i2p.streaming.inactivityTimeout 90*1000 Idle time before sending a keepalive
[U] - i2p.streaming.initialAckDelay 750 Delay before sending an ack
[U] - i2p.streaming.initialResendDelay 1000 The initial value of the resend delay field in the packet header, times 1000. Not fully implemented; see below.
[U] - i2p.streaming.initialRTO 9000 Initial timeout (if no sharing data available). As of release 0.9.8.
[U] - i2p.streaming.initialRTT 8000 Initial round trip time estimate (if no sharing data available). Disabled as of release 0.9.8; uses actual RTT.
[U] - i2p.streaming.initialWindowSize 6 (if no sharing data available) In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages.
[U] - i2p.streaming.limitAction reset What action to take when an incoming connection exceeds limits. Valid values are: reset (reset the connection); drop (drop the connection); or http (send a hardcoded HTTP 429 response). Any other value is a custom response to be sent. backslash-r and backslash-n will be replaced with CR and LF. As of release 0.9.34.
[U] - i2p.streaming.maxConcurrentStreams -1 (0 or negative value means unlimited) This is a total limit for incoming and outgoing combined.
[U] - i2p.streaming.maxConnsPerMinute 0 Incoming connection limit (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerHour 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxConnsPerDay 0 (per peer; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxMessageSize 1730 The MTU in bytes.
[U] - i2p.streaming.maxResends 8 Maximum number of retransmissions before failure.
[U] - i2p.streaming.maxTotalConnsPerMinute 0 Incoming connection limit (all peers; 0 means disabled) As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerHour 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxTotalConnsPerDay 0 (all peers; 0 means disabled) Use with caution as exceeding this will disable a server for a long time. As of release 0.7.14.
[U] - i2p.streaming.maxWindowSize 128
[U] - i2p.streaming.profile 1 (bulk) (2=interactive not supported) This doesn't currently do anything, but setting it to a value other than 1 will cause an error.
[U] - i2p.streaming.readTimeout -1 How long to block on read, in milliseconds. Negative means indefinitely.
[U] - i2p.streaming.slowStartGrowthRateFactor 1 When we're in slow start, we grow the window size at the rate of 1/(factor). In standard TCP, window sizes are in bytes, while in I2P, window sizes are in messages. A higher number means slower growth.
[U] - i2p.streaming.tcbcache.rttDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.rttdevDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.tcbcache.wdwDampening 0.75 Ref: RFC 2140. Floating point value. May be set only via context properties, not connection options. As of release 0.9.8.
[U] - i2p.streaming.writeTimeout -1 How long to block on write/flush, in milliseconds. Negative means indefinitely.
[C] - destination useful to consider adding to custom applications for client ocnfiguration
\* : I'd like to have something like this setting internal to samcatd, but it
might not always be relevant to pass it through to the real i2p router. Right
now, I'm leaning toward a samcatd specific setting, but maybe just alter the
behavior of this setting for use with samcatd instead? Probably just give
samcatd it's own thing.

42
docs/embedding.html Normal file
View File

@@ -0,0 +1,42 @@
<h1 id="embedding-i2p-support-in-your-go-application-with-samforwarder">Embedding i2p support in your Go application with samforwarder</h1>
<p>One neat thing you can do with samforwarder is make eepWeb(?) services configure themselves automatically by adding it to an existing Go application. To help with this process, the samforwarder/config/ file has a bunch of helper functions and a class for parsing configuration files directly. You can import it, add a few flags(or however you configure your service) and fire off the forwarder as a goroutne, all you have to do is configure it to forward the port used by your service. This makes it extremely easy to do, but it should only be used in this way for applications that would already be safe to host as services in i2p or other overlay networks. In particular, it should only be used for applications that dont require extensive login information and do not leak information at the application layer.</p>
<p>So without further ado, a blatant copy-paste of information that shouldnt have been in the README.md.</p>
<h2 id="static-eepsite-in-like-no-seconds">Static eepsite in like no seconds</h2>
<p>Using this port forwarder, its possible to create an instant eepsite from a folder full of html files(and the resources they call upon). Probably obviously to everybody reading this right now, but maybe not obviously to everyone reading this forever. An example of an application that works this way is available <a href="https://github.com/eyedeekay/eephttpd">here at my eephttpd repo</a>.</p>
<h2 id="quick-and-dirty-i2p-enabled-golang-web-applications">Quick-And-Dirty i2p-enabled golang web applications</h2>
<p>Normal web applications can easily add the ability to serve itself over i2p by importing and configuring this forwarding doodad. Wherever it takes the argument for the web servers listening host and/or port, pass that same host and/or port to a new instance of the “SAMForwarder” and then run the “Serve” function of the SAMForwarder as a goroutine. This simply forwards the running service to the i2p network, it doesnt do any filtering, and if your application establishes out-of-band connections, those may escape. Also, if your application is listening on all addresses, it will be visible from the local network.</p>
<p>Heres a simple example with a simple static file server:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb1-1" title="1">package main package main</a>
<a class="sourceLine" id="cb1-2" title="2"></a>
<a class="sourceLine" id="cb1-3" title="3">import ( import (</a>
<a class="sourceLine" id="cb1-4" title="4"> &quot;flag&quot; &quot;flag&quot;</a>
<a class="sourceLine" id="cb1-5" title="5"> &quot;log&quot; &quot;log&quot;</a>
<a class="sourceLine" id="cb1-6" title="6"> &quot;net/http&quot; &quot;net/http&quot;</a>
<a class="sourceLine" id="cb1-7" title="7">) )</a>
<a class="sourceLine" id="cb1-8" title="8"></a>
<a class="sourceLine" id="cb1-9" title="9"> &gt; import &quot;github.com/eyedeekay/sam-forwarder&quot;</a>
<a class="sourceLine" id="cb1-10" title="10"> &gt;</a>
<a class="sourceLine" id="cb1-11" title="11">func main() { func main() {</a>
<a class="sourceLine" id="cb1-12" title="12"> port := flag.String(&quot;p&quot;, &quot;8100&quot;, &quot;port to serve on&quot;) port := flag.String(&quot;p&quot;, &quot;8100&quot;, &quot;port to serve on&quot;)</a>
<a class="sourceLine" id="cb1-13" title="13"> directory := flag.String(&quot;d&quot;, &quot;.&quot;, &quot;the directory of static file to host&quot;) directory := flag.String(&quot;d&quot;, &quot;.&quot;, &quot;the directory of static file to host&quot;)</a>
<a class="sourceLine" id="cb1-14" title="14"> flag.Parse() flag.Parse()</a>
<a class="sourceLine" id="cb1-15" title="15"> &gt;</a>
<a class="sourceLine" id="cb1-16" title="16"> &gt; forwarder, err := samforwarder.NewSAMForwarderFromOptions(</a>
<a class="sourceLine" id="cb1-17" title="17"> &gt; samforwarder.SetHost(&quot;127.0.0.1&quot;),</a>
<a class="sourceLine" id="cb1-18" title="18"> &gt; samforwarder.SetPort(*port),</a>
<a class="sourceLine" id="cb1-19" title="19"> &gt; samforwarder.SetSAMHost(&quot;127.0.0.1&quot;),</a>
<a class="sourceLine" id="cb1-20" title="20"> &gt; samforwarder.SetSAMPort(&quot;7656&quot;),</a>
<a class="sourceLine" id="cb1-21" title="21"> &gt; samforwarder.SetName(&quot;staticfiles&quot;),</a>
<a class="sourceLine" id="cb1-22" title="22"> &gt; )</a>
<a class="sourceLine" id="cb1-23" title="23"> &gt; if err != nil {</a>
<a class="sourceLine" id="cb1-24" title="24"> &gt; log.Fatal(err.Error())</a>
<a class="sourceLine" id="cb1-25" title="25"> &gt; }</a>
<a class="sourceLine" id="cb1-26" title="26"> &gt; go forwarder.Serve()</a>
<a class="sourceLine" id="cb1-27" title="27"></a>
<a class="sourceLine" id="cb1-28" title="28"> http.Handle(&quot;/&quot;, http.FileServer(http.Dir(*directory))) http.Handle(&quot;/&quot;, http.FileServer(http.Dir(*directory)))</a>
<a class="sourceLine" id="cb1-29" title="29"></a>
<a class="sourceLine" id="cb1-30" title="30"> log.Printf(&quot;Serving %s on HTTP port: %s\n&quot;, *directory, *port) log.Printf(&quot;Serving %s on HTTP port: %s\n&quot;, *directory, *port)</a>
<a class="sourceLine" id="cb1-31" title="31"> log.Fatal(http.ListenAndServe(&quot;127.0.0.1:&quot;+*port, nil)) log.Fatal(http.ListenAndServe(&quot;127.0.0.1:&quot;+*port, nil))</a>
<a class="sourceLine" id="cb1-32" title="32">} }</a></code></pre></div>
<p><a href="https://gist.github.com/paulmach/7271283">This tiny file server taken from here and used for this example</a></p>
<h2 id="integrating-your-go-web-application-with-i2p-using-sam-forwarder">Integrating your Go web application with i2p using sam-forwarder</h2>

54
docs/index.html Normal file
View File

@@ -0,0 +1,54 @@
<h1 id="sam-forwarder">sam-forwarder</h1>
<p>Forward a local port to i2p over the SAM API, or proxy a destination to a port on the local host. This is a work-in-progress, but the basic functionality is, there and its already pretty useful. Everything TCP works, but UDP forwarding has much less real use than TCP. Turns out UDP was less broken than I thought though.</p>
<p>Since it seems to be doing UDP now, if youd like to donate to further development there are some wallet addresses at the bottom of this readme for now.</p>
<h2 id="getting">getting</h2>
<pre><code> go get -u github.com/eyedeekay/sam-forwarder/samcatd</code></pre>
<h2 id="building">building</h2>
<p>Just:</p>
<pre><code> make deps build</code></pre>
<p>and it will be in the folder ./bin/</p>
<p><a href="https://travis-ci.org/eyedeekay/sam-forwarder"><img src="https://travis-ci.org/eyedeekay/sam-forwarder.svg?branch=master" alt="Build Status" /></a></p>
<h2 id="usage">Usage:</h2>
<p>There are a number of ways to use sam-forwarder:</p>
<h3 id="usageconfiguration-as-an-applicationstart-here-for-samcatd"><a href="docs/USAGE.md">usage/configuration</a> as an application(Start here for samcatd)</h3>
<h3 id="embedding-in-other-applications"><a href="docs/EMBEDDING.md">embedding</a> in other applications</h3>
<h3 id="encapsulate-configuration-for-i2p-enabled-packages"><a href="docs/PACKAGECONF.md">encapsulate</a> configuration for i2p-enabled packages</h3>
<h3 id="implement-the-interface-for-fine-grained-control-over-sam-connections"><a href="interface/README.md">implement</a> the interface for fine-grained control over SAM connections</h3>
<h2 id="binaries">binaries</h2>
<p>Two binaries are produced by this repo. The first, ephsite, is only capable of running one tunnel at a time and doesnt have VPN support. Im only updating it to make sure that the embeddable interface in existing applications doesnt change. It will go away and be replaced with a wrapper to translate it to samcatd -s commands whenever I complete <a href="docs/CHECKLIST.md" class="uri">docs/CHECKLIST.md</a>.</p>
<p>The second, samcatd, is more advanced. It can start multiple tunnels with their own settings, or be used to start tunnels on the fly like ephsite by passing the -s option. Eventually Im probably just going to use this to configure all of my tunnels.</p>
<h1 id="current-limitations">Current limitations:</h1>
<p>I need to document it better. <a href="docs/USAGE.md">Besides fixing up the comments, this should help for now.</a>. I also need to control output verbosity better.</p>
<p>I need samcatd to accept a configuration folder identical to /etc/i2pd/tunnels.conf.d, since part of the point of this is to be compatible with i2pds tunnels configuration. Once this is done, Ill resume turning it into a .deb package.</p>
<p>It doesnt encrypt the .i2pkeys file by default, so if someone can steal them, then they can use them to construct tunnels to impersonate you. Experimental support for encrypted saves has been added. The idea is that only the person with the key will be able to decrypt and start the tunnels. It is up to the user to determine how to go about managing these keys. Right now this system is pretty bad. Ill be addressing that soon too.</p>
<p>TCP and UDP are both working now. Additional functionality might be added by adding other kinds of protocols overtop the TCP and UDP tunnels as a primitive. Theres a very basic UDP-based VPN available in samcatd by configuration-file only for now. Also it requires root. Probably need to split the VPN part into its own application. The package will need to give the application CAP_NET_BIND_SERVICE or something. This might work:</p>
<pre><code> sudo setcap cap_net_bind_service=epi ./bin/samcatd</code></pre>
<p>But I need to learn more about capabilities before I make that part of the thing.</p>
<p>Some kind of reverse-proxy or filter is also an obvious choice.</p>
<p>Ive only enabled the use of a subset of the i2cp and tunnel configuration options, the ones I use the most and for no other real reason assume other people use the most. Theyre pretty easy to add, its just boring. <em>If you</em> <em>want an i2cp or tunnel option that isnt available, bring it to my attention</em> <em>please.</em> Im pretty responsive when people actually contact me, itll probably be added within 24 hours. I intend to have configuration options for all relevant i2cp and tunnel options, which Im keeping track of <a href="config/CHECKLIST.md">here</a>.</p>
<p>I should probably have some options that are available in other general network utilities. Ive started to do this with samcatd.</p>
<p>I want it to be able to save ini files based on the settings used for a running forwarder. Should be easy, I just need to decide how I want to do it. Also to focus a bit more. Ive got more of a plan here now. tunconf has the loaded ini file inside it, and variables to track the state of the config options while running, and they can be switched to save options that might be changed via some interface or another.</p>
<p>Example tools built using this are being broken off into their own repos. Use the other repos where appropriate, so I can leave the examples un-messed with.</p>
<p>It would be really awesome if I could make this run on Android. So Ill make that happen eventually. I started a daemon for managing multiple tunnels and I figure I give it a web interface to configure stuff with. Ill probably put that in a different repo though. This is looking a little cluttered.</p>
<p>TLS configuration is experimental.</p>
<p>Ive made it self-supervising, but I need to make better use of contexts.</p>
<h2 id="stuff-thats-using-it">Stuff thats using it:</h2>
<p>Mostly mine, but this is all Free-as-in-Freedom for anyone to use:</p>
<ul>
<li><a href="https://github.com/eyedeekay/eephttpd">eephttpd</a></li>
<li><a href="https://github.com/eyedeekay/wikigopher">my fork of wikigopher</a></li>
<li><a href="https://github.com/s-gv/orangeforum">orangeforum</a></li>
</ul>
<h2 id="donate">Donate</h2>
<h3 id="monero-wallet-address">Monero Wallet Address</h3>
<p>XMR:43V6cTZrUfAb9JD6Dmn3vjdT9XxLbiE27D1kaoehb359ACaHs8191mR4RsJH7hGjRTiAoSwFQAVdsCBToXXPAqTMDdP2bZB</p>
<h3 id="bitcoin-wallet-address">Bitcoin Wallet Address</h3>
<p>BTC:159M8MEUwhTzE9RXmcZxtigKaEjgfwRbHt</p>
<h2 id="index">Index</h2>
<ul>
<li><a href="index.html">readme</a></li>
<li><a href="usage.html">usage</a></li>
<li><a href="packageconf.html">configuration</a></li>
<li><a href="embedding.html">embedding</a></li>
<li><a href="interface.htnl">interface</a></li>
</ul>

2
docs/interface.html Normal file
View File

@@ -0,0 +1,2 @@
<h1 id="implementing-the-sam-forwarder-interface">Implementing the sam-forwarder interface</h1>
<p>The sam-forwrder interface(used int the Go sense of the word interface) is used to create custom types of tunnels.</p>

1
docs/packageconf.html Normal file
View File

@@ -0,0 +1 @@
<h1 id="encapsulating-and-packaging-application-configuration-with-samcatd">Encapsulating and Packaging Application Configuration with samcatd</h1>

194
docs/usage.html Normal file
View File

@@ -0,0 +1,194 @@
<h1 id="samcatd---router-independent-tunnel-management-for-i2p">samcatd - Router-independent tunnel management for i2p</h1>
<p>samcatd is a daemon which runs a group of forwarding proxies to provide services over i2p independent of the router. It also serves as a generalized i2p networking utility for power-users. Its intended to be a Swiss-army knife for the SAM API.</p>
<h2 id="usage">usage:</h2>
<pre><code>flag needs an argument: -h
Usage of ./bin/samcatd:
-a string
Type of access list to use, can be &quot;allowlist&quot; &quot;blocklist&quot; or &quot;none&quot;. (default &quot;none&quot;)
-c Client proxy mode(true or false)
-conv string
Display the base32 and base64 values of a specified .i2pkeys file
-cr string
Encrypt/decrypt the key files with a passfile
-css string
custom CSS for web interface (default &quot;css/styles.css&quot;)
-ct int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-d string
Directory to save tunnel configuration file in.
-de string
Destination to connect client&#39;s to by default.
-f string
Use an ini file for configuration(config file options override passed arguments for now.) (default &quot;none&quot;)
-h string
Target host(Host of service to forward to i2p) (default &quot;127.0.0.1&quot;)
-i string
Destination for client tunnels. Ignored for service tunnels. (default &quot;none&quot;)
-ib int
Set inbound tunnel backup quantity(0 to 5) (default 2)
-ih
Inject X-I2P-DEST headers
-il int
Set inbound tunnel length(0 to 7) (default 3)
-iq int
Set inbound tunnel quantity(0 to 15) (default 6)
-iv int
Set inbound tunnel length variance(-7 to 7)
-js string
custom JS for web interface (default &quot;js/scripts.js&quot;)
-k string
key for encrypted leaseset (default &quot;none&quot;)
-l Use an encrypted leaseset(true or false) (default true)
-littleboss string
instruct the littleboss:
start: start and manage this process using service name &quot;service-name&quot;
stop: signal the littleboss to shutdown the process
status: print statistics about the running littleboss
reload: restart the managed process using the executed binary
bypass: disable littleboss, run the program directly (default &quot;bypass&quot;)
-n string
Tunnel name, this must be unique but can be anything. (default &quot;forwarder&quot;)
-ob int
Set outbound tunnel backup quantity(0 to 5) (default 2)
-ol int
Set outbound tunnel length(0 to 7) (default 3)
-oq int
Set outbound tunnel quantity(0 to 15) (default 6)
-ov int
Set outbound tunnel length variance(-7 to 7)
-p string
Target port(Port of service to forward to i2p) (default &quot;8081&quot;)
-pk string
private key for encrypted leaseset (default &quot;none&quot;)
-psk string
private signing key for encrypted leaseset (default &quot;none&quot;)
-r Reduce tunnel quantity when idle(true or false)
-rq int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-rt int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-s Start a tunnel with the passed parameters(Otherwise, they will be treated as default values.)
-sh string
SAM host (default &quot;127.0.0.1&quot;)
-sp string
SAM port (default &quot;7656&quot;)
-st string
Signature type
-t Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.
-tls string
(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)
-u UDP mode(true or false)
-w Start web administration interface
-wp string
Web port (default &quot;7957&quot;)
-x Close tunnel idle(true or false)
-z Uze gzip(true or false)
-zi
Allow zero-hop, non-anonymous tunnels in(true or false)
-zo
Allow zero-hop, non-anonymous tunnels out(true or false)</code></pre>
<h1 id="managing-samcatd-save-encryption-keys">managing samcatd save-encryption keys</h1>
<p>In order to keep from saving the .i2pkeys files in plaintext format, samcatd can optionally generate a key and encrypt the .i2pkeys files securely. Of course, to fully benefit from this arrangement, you need to move those keys away from the machine where the tunnel keys(the .i2pkeys file) are located, or protect them in some other way(sandboxing, etc). If you want to use encrypted .i2pkeys files, you can specify a key file to use with the -cr option on the terminal or with keyfile option in the .ini file.</p>
<h1 id="example-config---valid-for-both-ephsite-and-samcat">example config - valid for both ephsite and samcat</h1>
<p>Options are still being added, pretty much as fast as I can put them in. For up-to-the-minute options, see <a href="config/CHECKLIST.md">the checklist</a></p>
<p>(<strong>ephsite</strong> will only use top-level options, but they can be labeled or unlabeled)</p>
<p>(<strong>samcatd</strong> treats the first set of options it sees as the default, and does not start tunnels based on unlabeled options unless passed the -s flag.)</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode ini"><code class="sourceCode ini"><a class="sourceLine" id="cb2-1" title="1"></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="co">## Defaults, these are only invoked with the -start option or if labeled tunnels</span></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="co">## are not present(samcatd instructions). **THESE** are the correct config files</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="co">## to use as defaults, and not the ones in ../sam-forwarder/tunnels.ini, which</span></a>
<a class="sourceLine" id="cb2-5" title="5"><span class="co">## are used for testing settings availability only.</span></a>
<a class="sourceLine" id="cb2-6" title="6"></a>
<a class="sourceLine" id="cb2-7" title="7"><span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="dt">inbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="dt">outbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span></a>
<a class="sourceLine" id="cb2-11" title="11"><span class="dt">inbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-12" title="12"><span class="dt">outbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-13" title="13"><span class="dt">inbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span></a>
<a class="sourceLine" id="cb2-14" title="14"><span class="dt">outbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span></a>
<a class="sourceLine" id="cb2-15" title="15"><span class="dt">inbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span></a>
<a class="sourceLine" id="cb2-16" title="16"><span class="dt">outbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span></a>
<a class="sourceLine" id="cb2-17" title="17"><span class="dt">i2cp.encryptLeaseSet </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span></a>
<a class="sourceLine" id="cb2-18" title="18"><span class="dt">gzip </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span></a>
<a class="sourceLine" id="cb2-19" title="19"><span class="dt">i2cp.reduceOnIdle </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span></a>
<a class="sourceLine" id="cb2-20" title="20"><span class="dt">i2cp.reduceIdleTime </span><span class="ot">=</span><span class="st"> </span><span class="dv">3000000</span></a>
<a class="sourceLine" id="cb2-21" title="21"><span class="dt">i2cp.reduceQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">2</span></a>
<a class="sourceLine" id="cb2-22" title="22"><span class="dt">i2cp.enableWhiteList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span></a>
<a class="sourceLine" id="cb2-23" title="23"><span class="dt">i2cp.enableBlackList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span></a>
<a class="sourceLine" id="cb2-24" title="24"><span class="dt">keyfile </span><span class="ot">=</span><span class="st"> &quot;/usr/share/samcatd/samcatd&quot;</span></a>
<a class="sourceLine" id="cb2-25" title="25"></a>
<a class="sourceLine" id="cb2-26" title="26"><span class="co">#[sam-forwarder-tcp-server]</span></a>
<a class="sourceLine" id="cb2-27" title="27"><span class="co">#type = server</span></a>
<a class="sourceLine" id="cb2-28" title="28"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-29" title="29"><span class="co">#port = 8081</span></a>
<a class="sourceLine" id="cb2-30" title="30"><span class="co">#inbound.length = 3</span></a>
<a class="sourceLine" id="cb2-31" title="31"><span class="co">#outbound.length = 3</span></a>
<a class="sourceLine" id="cb2-32" title="32"><span class="co">#keys = forwarder</span></a>
<a class="sourceLine" id="cb2-33" title="33"></a>
<a class="sourceLine" id="cb2-34" title="34"><span class="kw">[sam-forwarder-tcp-client]</span></a>
<a class="sourceLine" id="cb2-35" title="35"><span class="dt">type </span><span class="ot">=</span><span class="st"> client</span></a>
<a class="sourceLine" id="cb2-36" title="36"><span class="dt">host </span><span class="ot">=</span><span class="st"> </span><span class="dv">127</span><span class="st">.</span><span class="dv">0</span><span class="st">.</span><span class="fl">0.1</span></a>
<a class="sourceLine" id="cb2-37" title="37"><span class="dt">port </span><span class="ot">=</span><span class="st"> </span><span class="dv">8082</span></a>
<a class="sourceLine" id="cb2-38" title="38"><span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-39" title="39"><span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span></a>
<a class="sourceLine" id="cb2-40" title="40"><span class="dt">destination </span><span class="ot">=</span><span class="st"> i2p-projekt.i2p</span></a>
<a class="sourceLine" id="cb2-41" title="41"><span class="dt">keys </span><span class="ot">=</span><span class="st"> forwarder-two</span></a>
<a class="sourceLine" id="cb2-42" title="42"></a>
<a class="sourceLine" id="cb2-43" title="43"><span class="co">#[sam-forwarder-udp-server]</span></a>
<a class="sourceLine" id="cb2-44" title="44"><span class="co">#type = udpserver</span></a>
<a class="sourceLine" id="cb2-45" title="45"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-46" title="46"><span class="co">#port = 8084</span></a>
<a class="sourceLine" id="cb2-47" title="47"><span class="co">#inbound.length = 6</span></a>
<a class="sourceLine" id="cb2-48" title="48"><span class="co">#outbound.length = 3</span></a>
<a class="sourceLine" id="cb2-49" title="49"><span class="co">#keys = forwarder-four</span></a>
<a class="sourceLine" id="cb2-50" title="50"></a>
<a class="sourceLine" id="cb2-51" title="51"><span class="co">#[sam-forwarder-udp-client]</span></a>
<a class="sourceLine" id="cb2-52" title="52"><span class="co">#type = udpclient</span></a>
<a class="sourceLine" id="cb2-53" title="53"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-54" title="54"><span class="co">#port = 8083</span></a>
<a class="sourceLine" id="cb2-55" title="55"><span class="co">#inbound.length = 3</span></a>
<a class="sourceLine" id="cb2-56" title="56"><span class="co">#outbound.length = 3</span></a>
<a class="sourceLine" id="cb2-57" title="57"><span class="co">#destination = i2p-projekt.i2p</span></a>
<a class="sourceLine" id="cb2-58" title="58"><span class="co">#keys = forwarder-three</span></a>
<a class="sourceLine" id="cb2-59" title="59"></a>
<a class="sourceLine" id="cb2-60" title="60"><span class="co">#[sam-forwarder-tcp-http-server]</span></a>
<a class="sourceLine" id="cb2-61" title="61"><span class="co">#type = http</span></a>
<a class="sourceLine" id="cb2-62" title="62"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-63" title="63"><span class="co">#port = 8085</span></a>
<a class="sourceLine" id="cb2-64" title="64"><span class="co">#inbound.length = 3</span></a>
<a class="sourceLine" id="cb2-65" title="65"><span class="co">#outbound.length = 3</span></a>
<a class="sourceLine" id="cb2-66" title="66"><span class="co">#keys = forwarder-five</span></a>
<a class="sourceLine" id="cb2-67" title="67"></a>
<a class="sourceLine" id="cb2-68" title="68"><span class="co">#[sam-forwarder-vpn-server]</span></a>
<a class="sourceLine" id="cb2-69" title="69"><span class="co">#type = udpserver</span></a>
<a class="sourceLine" id="cb2-70" title="70"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-71" title="71"><span class="co">#port = 8084</span></a>
<a class="sourceLine" id="cb2-72" title="72"><span class="co">#inbound.length = 2</span></a>
<a class="sourceLine" id="cb2-73" title="73"><span class="co">#outbound.length = 2</span></a>
<a class="sourceLine" id="cb2-74" title="74"><span class="co">#inbound.backupQuantity = 3</span></a>
<a class="sourceLine" id="cb2-75" title="75"><span class="co">#outbound.backupQuantity = 3</span></a>
<a class="sourceLine" id="cb2-76" title="76"><span class="co">#inbound.quantity = 5</span></a>
<a class="sourceLine" id="cb2-77" title="77"><span class="co">#outbound.quantity = 5</span></a>
<a class="sourceLine" id="cb2-78" title="78"><span class="co">#i2cp.reduceOnIdle = true</span></a>
<a class="sourceLine" id="cb2-79" title="79"><span class="co">#i2cp.reduceIdleTime = 3000000</span></a>
<a class="sourceLine" id="cb2-80" title="80"><span class="co">#i2cp.reduceQuantity = 2</span></a>
<a class="sourceLine" id="cb2-81" title="81"><span class="co">#i2cp.closeOnIdle = false</span></a>
<a class="sourceLine" id="cb2-82" title="82"><span class="co">#keys = i2pvpnserver</span></a>
<a class="sourceLine" id="cb2-83" title="83"></a>
<a class="sourceLine" id="cb2-84" title="84"><span class="co">#[sam-forwarder-vpn-client]</span></a>
<a class="sourceLine" id="cb2-85" title="85"><span class="co">#type = udpclient</span></a>
<a class="sourceLine" id="cb2-86" title="86"><span class="co">#host = 127.0.0.1</span></a>
<a class="sourceLine" id="cb2-87" title="87"><span class="co">#port = 8085</span></a>
<a class="sourceLine" id="cb2-88" title="88"><span class="co">#inbound.length = 2</span></a>
<a class="sourceLine" id="cb2-89" title="89"><span class="co">#outbound.length = 2</span></a>
<a class="sourceLine" id="cb2-90" title="90"><span class="co">#inbound.backupQuantity = 3</span></a>
<a class="sourceLine" id="cb2-91" title="91"><span class="co">#outbound.backupQuantity = 3</span></a>
<a class="sourceLine" id="cb2-92" title="92"><span class="co">#inbound.quantity = 5</span></a>
<a class="sourceLine" id="cb2-93" title="93"><span class="co">#outbound.quantity = 5</span></a>
<a class="sourceLine" id="cb2-94" title="94"><span class="co">#i2cp.reduceOnIdle = true</span></a>
<a class="sourceLine" id="cb2-95" title="95"><span class="co">#i2cp.reduceIdleTime = 3000000</span></a>
<a class="sourceLine" id="cb2-96" title="96"><span class="co">#i2cp.reduceQuantity = 2</span></a>
<a class="sourceLine" id="cb2-97" title="97"><span class="co">#destination = adestinationisrequiredorbespecifiedatruntime.i2p</span></a>
<a class="sourceLine" id="cb2-98" title="98"><span class="co">#keys = i2pvpnclient</span></a></code></pre></div>

15
etc/i2pvpn/i2pvpn.ini Normal file
View File

@@ -0,0 +1,15 @@
[I2PVPNServer]
type = udpserver
host = 127.0.0.1
port = 8084
inbound.length = 2
outbound.length = 2
inbound.backupQuantity = 3
outbound.backupQuantity = 3
inbound.quantity = 5
outbound.quantity = 5
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 2
i2cp.closeOnIdle = false
keys = i2pvpnserver

View File

@@ -0,0 +1,15 @@
[I2PVPNClient]
type = udpclient
host = 127.0.0.1
port = 8085
inbound.length = 2
outbound.length = 2
inbound.backupQuantity = 3
outbound.backupQuantity = 3
inbound.quantity = 5
outbound.quantity = 5
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 2
#destination = adestinationisrequiredorbespecifiedatruntime.i2p
keys = i2pvpnclient

91
etc/init.d/samcatd Normal file
View File

@@ -0,0 +1,91 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: samcatd
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: <DESCRIPTION>
### END INIT INFO
SCRIPT='/usr/local/bin/samcatd -f /etc/samcatd/tunnels.ini'
RUNAS=samcatd
PIDFILE=/var/run/samcatd/samcatd.pid
RUNFOLDER=/var/run/samcatd
LOGFILE=/var/log/samcatd/samcatd.log
start() {
if [ -f "$PIDFILE" ]; then
echo 'Service already running' >&2
return 1
fi
echo 'Starting destination-isolating proxy service…' >&2
start-stop-daemon -S -b -q -d "$RUNFOLDER" -g "$RUNAS" -c "$RUNAS" -p "$PIDFILE" \
--startas /bin/bash -- -c "exec $SCRIPT > $LOGFILE 2>&1"
echo $! > "$PIDFILE"
echo "Service started: $SCRIPT" >&2
cat "$PIDFILE" >&2
}
stop() {
if [ ! -f "$PIDFILE" ]; then
echo 'Service not running' >&2
return 1
fi
echo 'Stopping destination-isolating proxy service…' >&2
start-stop-daemon -K -q -d "$RUNFOLDER" -g "$RUNAS" -c "$RUNAS" -p "$PIDFILE" \
--startas /bin/bash -- -c "exec $SCRIPT > $LOGFILE 2>&1"
echo "Service stopped: $SCRIPT" >&2
rm -f "$PIDFILE"
}
status() {
if [ -f "$PIDFILE" ]; then
start-stop-daemon -T -q -d "$RUNFOLDER" -g "$RUNAS" -c "$RUNAS" -p "$PIDFILE" \
--startas /bin/bash -- -c "exec $SCRIPT > $LOGFILE 2>&1"
echo 'Currently open pipes:' >&2
ls /var/run/samcatd/* >&2
tail $LOGFILE >&2
return 1
else
echo 'Service not running' >&2
ls /var/run/samcatd >&2
return 1
fi
echo 'Starting destination-isolating proxy service…' >&2
}
uninstall() {
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
local SURE
read SURE
if [ "$SURE" = "yes" ]; then
stop
rm -f "$PIDFILE"
echo "Notice: log file is not be removed: '$LOGFILE'" >&2
update-rc.d -f samcatd remove
rm -fv "$0"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
uninstall)
uninstall
;;
restart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart|uninstall}"
esac

View File

@@ -1,25 +1,22 @@
##Example configuration file, all crazy options enabled. Intended for adjustment.
## DO NOT USE THESE AS DEFAULTS. THEY ARE FOR TESTING.
[ephsite]
type = server
host = 127.0.0.1
port = 8081
inbound.length = 3
outbound.length = 6
#inbound.lengthVariance = 6
#outbound.lengthVariance = 6
#inbound.backupQuantity = 3
#outbound.backupQuantity = 5
#inbound.quantity = 15
#outbound.quantity = 15
#inbound.allowZeroHop = true
#outbound.allowZeroHop = true
#i2cp.encryptLeaseSet = true
#gzip = true
#i2cp.reduceOnIdle = true
#i2cp.reduceIdleTime = 3000000
#i2cp.reduceQuantity = 4
#i2cp.enableWhiteList = false
#i2cp.enableBlackList = true
#i2cp.accessList = BASE64KEYSSEPARATEDBY,COMMAS
#keys = forwarder
inbound.length = 1
outbound.length = 2
inbound.lengthVariance = 3
outbound.lengthVariance = 4
inbound.backupQuantity = 5
outbound.backupQuantity = 4
inbound.quantity = 3
outbound.quantity = 2
inbound.allowZeroHop = false
outbound.allowZeroHop = false
i2cp.encryptLeaseSet = false
gzip = true
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 3000000
i2cp.reduceQuantity = 2
i2cp.enableWhiteList = false
i2cp.enableBlackList = false

9897
etc/samcatd/hashwords.txt Normal file

File diff suppressed because it is too large Load Diff

83
etc/samcatd/tunnels.ini Normal file
View File

@@ -0,0 +1,83 @@
## Defaults, these are only invoked with the -start option or if labeled tunnels
## are not present(samcatd instructions). **THESE** are the correct config files
## to use as defaults, and not the ones in ../sam-forwarder/tunnels.ini, which
## are used for testing settings availability only.
inbound.length = 3
outbound.length = 3
inbound.lengthVariance = 1
outbound.lengthVariance = 1
inbound.backupQuantity = 1
outbound.backupQuantity = 1
inbound.quantity = 2
outbound.quantity = 2
inbound.allowZeroHop = false
outbound.allowZeroHop = false
i2cp.encryptLeaseSet = false
gzip = true
i2cp.reduceOnIdle = true
i2cp.reduceIdleTime = 300000
i2cp.reduceQuantity = 2
i2cp.enableWhiteList = false
i2cp.enableBlackList = false
#keyfile = "/usr/share/samcatd/samcatd"
[sam-forwarder-tcp-server]
type = server
host = 127.0.0.1
port = 7669
inbound.length = 2
outbound.length = 2
keys = tcpserver
[sam-forwarder-tcp-client]
type = client
host = 127.0.0.1
port = 8082
inbound.length = 2
outbound.length = 3
destination = i2p-projekt.i2p
keys = tcpclient
[sam-forwarder-udp-server]
type = udpserver
host = 127.0.0.1
port = 8084
inbound.length = 3
outbound.length = 3
keys = udpserver
[sam-forwarder-udp-client]
type = udpclient
host = 127.0.0.1
port = 8083
inbound.length = 3
outbound.length = 3
destination = icdj5g5u4jwwyjoinucty223s2yrq6pzxcqfwmyrmkp7ssn2fjlq.b32.i2p
keys = udpclient
[sam-forwarder-tcp-http-server]
type = http
host = 127.0.0.1
port = 8085
inbound.length = 3
outbound.length = 3
keys = httpserver
#[sam-forwarder-tcp-http-client]
#type = httpclient
#host = 127.0.0.1
#port = 8086
#inbound.length = 3
#outbound.length = 3
#keys = proxy
[sam-forwarder-tcp-socks-outproxy]
type = client
host = 127.0.0.1
port = 8087
inbound.length = 2
outbound.length = 3
destination = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq.b32.i2p
keys = tcpclient

View File

@@ -1,126 +0,0 @@
package main
/*
WARNING: This is not the official version of eephttpd. It is an older
verion I use to test new sam-forwarder features. It is not intended for
use in production.
*/
import (
"crypto/tls"
"flag"
"log"
"net/http"
"path/filepath"
)
import (
"github.com/eyedeekay/sam-forwarder"
"github.com/eyedeekay/sam-forwarder/config"
)
var cfg = &tls.Config{
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
PreferServerCipherSuites: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
}
var (
host = flag.String("a", "127.0.0.1", "hostname to serve on")
port = flag.String("p", "7880", "port to serve locally on")
samhost = flag.String("sh", "127.0.0.1", "sam host to connect to")
samport = flag.String("sp", "7656", "sam port to connect to")
directory = flag.String("d", "./www", "the directory of static files to host(default ./www)")
sdirectory = flag.String("s", ".", "the directory to save the keys in(default ./)")
usei2p = flag.Bool("i", true, "save i2p keys(and thus destinations) across reboots")
servicename = flag.String("n", "static-eepSite", "name to give the tunnel(default static-eepSite)")
useCompression = flag.Bool("g", true, "Uze gzip(true or false)")
injectHeaders = flag.Bool("x", true, "Inject X-I2P-DEST headers")
accessListType = flag.String("l", "none", "Type of access list to use, can be \"whitelist\" \"blacklist\" or \"none\".")
encryptLeaseSet = flag.Bool("c", false, "Use an encrypted leaseset(true or false)")
allowZeroHop = flag.Bool("z", false, "Allow zero-hop, non-anonymous tunnels(true or false)")
reduceIdle = flag.Bool("r", false, "Reduce tunnel quantity when idle(true or false)")
reduceIdleTime = flag.Int("rt", 600000, "Reduce tunnel quantity after X (milliseconds)")
reduceIdleQuantity = flag.Int("rc", 3, "Reduce idle tunnel quantity to X (0 to 5)")
inLength = flag.Int("il", 3, "Set inbound tunnel length(0 to 7)")
outLength = flag.Int("ol", 3, "Set outbound tunnel length(0 to 7)")
inQuantity = flag.Int("iq", 8, "Set inbound tunnel quantity(0 to 15)")
outQuantity = flag.Int("oq", 8, "Set outbound tunnel quantity(0 to 15)")
inVariance = flag.Int("iv", 0, "Set inbound tunnel length variance(-7 to 7)")
outVariance = flag.Int("ov", 0, "Set outbound tunnel length variance(-7 to 7)")
inBackupQuantity = flag.Int("ib", 4, "Set inbound tunnel backup quantity(0 to 5)")
outBackupQuantity = flag.Int("ob", 4, "Set outbound tunnel backup quantity(0 to 5)")
iniFile = flag.String("f", "none", "Use an ini file for configuration")
useTLS = flag.Bool("t", false, "Generate or use an existing TLS certificate")
certFile = flag.String("m", "cert", "Certificate name to use")
)
func main() {
flag.Parse()
var forwarder *samforwarder.SAMForwarder
var err error
config := i2ptunconf.NewI2PBlankTunConf()
if *iniFile != "none" {
config, err = i2ptunconf.NewI2PTunConf(*iniFile)
}
config.TargetHost = config.GetHost(*host, "127.0.0.1")
config.TargetPort = config.GetPort(*port, "7880")
config.SaveFile = config.GetSaveFile(*usei2p, true)
config.SaveDirectory = config.GetDir(*sdirectory, "../")
config.SamHost = config.GetSAMHost(*samhost, "127.0.0.1")
config.SamPort = config.GetSAMPort(*samport, "7656")
config.TunName = config.GetKeys(*servicename, "static-eepSite")
config.InLength = config.GetInLength(*inLength, 3)
config.OutLength = config.GetOutLength(*outLength, 3)
config.InVariance = config.GetInVariance(*inVariance, 0)
config.OutVariance = config.GetOutVariance(*outVariance, 0)
config.InQuantity = config.GetInQuantity(*inQuantity, 6)
config.OutQuantity = config.GetOutQuantity(*outQuantity, 6)
config.InBackupQuantity = config.GetInBackups(*inBackupQuantity, 5)
config.OutBackupQuantity = config.GetOutBackups(*outBackupQuantity, 5)
config.EncryptLeaseSet = config.GetEncryptLeaseset(*encryptLeaseSet, false)
config.InAllowZeroHop = config.GetInAllowZeroHop(*allowZeroHop, false)
config.OutAllowZeroHop = config.GetOutAllowZeroHop(*allowZeroHop, false)
config.UseCompression = config.GetUseCompression(*useCompression, true)
config.ReduceIdle = config.GetReduceOnIdle(*reduceIdle, true)
config.ReduceIdleTime = config.GetReduceIdleTime(*reduceIdleTime, 600000)
config.ReduceIdleQuantity = config.GetReduceIdleQuantity(*reduceIdleQuantity, 2)
config.CloseIdleTime = config.GetCloseIdleTime(*reduceIdleTime, 600000)
config.AccessListType = config.GetAccessListType(*accessListType, "none")
config.Type = config.GetType(false, false, *injectHeaders, "server")
if forwarder, err = i2ptunconf.NewSAMForwarderFromConf(config); err != nil {
log.Fatal(err.Error())
}
go forwarder.Serve()
if *useTLS {
srv := &http.Server{
Addr: *host + ":" + *port,
Handler: http.FileServer(http.Dir(*directory)),
TLSConfig: cfg,
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
}
log.Printf("Serving %s on HTTPS port: %s\n\t and on \n%s", *directory, *port, forwarder.Base32())
log.Fatal(
srv.ListenAndServeTLS(
filepath.Join(*sdirectory+"/", *certFile+".crt"),
filepath.Join(*sdirectory+"/", *certFile+".key"),
),
)
} else {
log.Printf("Serving %s on HTTP port: %s\n\t and on \n%s", *directory, *port, forwarder.Base32())
log.Fatal(
http.ListenAndServe(
*host+":"+*port,
http.FileServer(http.Dir(*directory)),
),
)
}
}

View File

@@ -1,33 +0,0 @@
package main package main
import ( import (
"flag" "flag"
"log" "log"
"net/http" "net/http"
) )
> import "github.com/eyedeekay/sam-forwarder"
>
func main() { func main() {
port := flag.String("p", "8101", "port to serve on") | port := flag.String("p", "8100", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host") directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse() flag.Parse()
> forwarder, err := samforwarder.NewSAMForwarderFromOptions(
> samforwarder.SetHost("127.0.0.1"),
> samforwarder.SetPort(*port),
> samforwarder.SetSAMHost("127.0.0.1"),
> samforwarder.SetSAMPort("7656"),
> samforwarder.SetName("staticfiles"),
> )
> if err != nil {
> log.Fatal(err.Error())
> }
> go forwarder.Serve()
>
http.Handle("/", http.FileServer(http.Dir(*directory))) http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port) | log.Printf("Serving %s on HTTP port: %s\n", *directory, *port, "and on",
log.Fatal(http.ListenAndServe(":"+*port, nil)) | forwarder.Base32()+".b32.i2p")
> log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil))
} }

View File

@@ -1,33 +0,0 @@
package main
import (
"flag"
"log"
"net/http"
)
import "github.com/eyedeekay/sam-forwarder"
func main() {
port := flag.String("p", "8100", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse()
forwarder, err := samforwarder.NewSAMForwarderFromOptions(
samforwarder.SetHost("127.0.0.1"),
samforwarder.SetPort(*port),
samforwarder.SetSAMHost("127.0.0.1"),
samforwarder.SetSAMPort("7656"),
samforwarder.SetName("staticfiles"),
)
if err != nil {
log.Fatal(err.Error())
}
go forwarder.Serve()
http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port, "and on",
forwarder.Base32()+".b32.i2p")
log.Fatal(http.ListenAndServe("127.0.0.1:"+*port, nil))
}

View File

@@ -1,138 +0,0 @@
<h1 id="ephsite---easy-forwarding-of-local-services-to-i2p">ephsite - Easy forwarding of local services to i2p</h1>
<p>ephsite is a forwarding proxy designed to configure a tunnel for use with i2p. It can be used to easily forward a local service to the i2p network using i2p's SAM API instead of the tunnel interface.</p>
<h2 id="usage">usage:</h2>
<pre><code>Usage of ./bin/ephsite:
-access string
Type of access list to use, can be &quot;whitelist&quot; &quot;blacklist&quot; or &quot;none&quot;. (default &quot;none&quot;)
-accesslist value
Specify an access list member(can be used multiple times)
-client
Client proxy mode(true or false)
-close
Close tunnel idle(true or false)
-closetime int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-dest string
Destination for client tunnels. Ignored for service tunnels. (default &quot;none&quot;)
-dir string
Directory to save tunnel configuration file in.
-encryptlease
Use an encrypted leaseset(true or false) (default true)
-gzip
Uze gzip(true or false)
-host string
Target host(Host of service to forward to i2p) (default &quot;127.0.0.1&quot;)
-inback int
Set inbound tunnel backup quantity(0 to 5) (default 4)
-incount int
Set inbound tunnel quantity(0 to 15) (default 6)
-ini string
Use an ini file for configuration(config file options override passed arguments for now.) (default &quot;none&quot;)
-inlen int
Set inbound tunnel length(0 to 7) (default 3)
-invar int
Set inbound tunnel length variance(-7 to 7)
-lsk string
path to saved encrypted leaseset keys (default &quot;none&quot;)
-name string
Tunnel name, this must be unique but can be anything. (default &quot;forwarder&quot;)
-outback int
Set outbound tunnel backup quantity(0 to 5) (default 4)
-outcount int
Set outbound tunnel quantity(0 to 15) (default 6)
-outlen int
Set outbound tunnel length(0 to 7) (default 3)
-outvar int
Set outbound tunnel length variance(-7 to 7)
-port string
Target port(Port of service to forward to i2p) (default &quot;8081&quot;)
-reduce
Reduce tunnel quantity when idle(true or false)
-reducecount int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-reducetime int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-samhost string
SAM host (default &quot;127.0.0.1&quot;)
-samport string
SAM port (default &quot;7656&quot;)
-save
Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.
-tlsport string
(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)
-udp
UDP mode(true or false)
-zeroin
Allow zero-hop, non-anonymous tunnels in(true or false)
-zeroout
Allow zero-hop, non-anonymous tunnels out(true or false)</code></pre>
<h1 id="eephttpd---static-file-server-automatically-forwarded-to-i2p">eephttpd - Static file server automatically forwarded to i2p</h1>
<h2 id="usage-1">usage:</h2>
<p>eephttpd is a static http server which automatically runs on i2p with the help of the SAM bridge. By default it will only be available from the localhost and it's i2p tunnel. It can be masked from the localhost using a container.</p>
<pre><code>Usage of ./bin/eephttpd:
-a string
hostname to serve on (default &quot;127.0.0.1&quot;)
-c Use an encrypted leaseset(true or false)
-d string
the directory of static files to host(default ./www) (default &quot;./www&quot;)
-f string
Use an ini file for configuration (default &quot;none&quot;)
-g Uze gzip(true or false) (default true)
-i save i2p keys(and thus destinations) across reboots (default true)
-ib int
Set inbound tunnel backup quantity(0 to 5) (default 4)
-il int
Set inbound tunnel length(0 to 7) (default 3)
-iq int
Set inbound tunnel quantity(0 to 15) (default 8)
-iv int
Set inbound tunnel length variance(-7 to 7)
-l string
Type of access list to use, can be &quot;whitelist&quot; &quot;blacklist&quot; or &quot;none&quot;. (default &quot;none&quot;)
-m string
Certificate name to use (default &quot;cert&quot;)
-n string
name to give the tunnel(default static-eepSite) (default &quot;static-eepSite&quot;)
-ob int
Set outbound tunnel backup quantity(0 to 5) (default 4)
-ol int
Set outbound tunnel length(0 to 7) (default 3)
-oq int
Set outbound tunnel quantity(0 to 15) (default 8)
-ov int
Set outbound tunnel length variance(-7 to 7)
-p string
port to serve locally on (default &quot;7880&quot;)
-r Reduce tunnel quantity when idle(true or false)
-rc int
Reduce idle tunnel quantity to X (0 to 5) (default 3)
-rt int
Reduce tunnel quantity after X (milliseconds) (default 600000)
-s string
the directory to save the keys in(default ./) (default &quot;.&quot;)
-sh string
sam host to connect to (default &quot;127.0.0.1&quot;)
-sp string
sam port to connect to (default &quot;7656&quot;)
-t Generate or use an existing TLS certificate
-z Allow zero-hop, non-anonymous tunnels(true or false)</code></pre>
<h3 id="build-in-docker">build in docker</h3>
<pre><code>docker build --build-arg user=eephttpd --build-arg path=example/www -f Dockerfile -t eyedeekay/eephttpd .</code></pre>
<h3 id="run-in-docker">Run in docker</h3>
<pre><code>docker run -i -t -d \
--name eephttpd-volume \
--volume eephttpd:/home/eephttpd/ \
eyedeekay/eephttpd</code></pre>
<pre><code>docker run -i -t -d \
--network si \
--env samhost=sam-host \
--env samport=7656 \
--env args=-r # Additional arguments to pass to eephttpd\
--network-alias eephttpd \
--hostname eephttpd \
--name eephttpd \
--restart always \
--volumes-from eephttpd-volume \
eyedeekay/eephttpd</code></pre>
<h2 id="instance">instance</h2>
<p>a running instance of eephttpd with the example index file is availble on</p>

View File

@@ -1,338 +0,0 @@
package samforwarder
import (
"fmt"
"strconv"
)
//ClientOption is a SAMClientForwarder Option
type ClientOption func(*SAMClientForwarder) error
//SetClientFilePath sets the host of the SAMClientForwarder's SAM bridge
func SetClientFilePath(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.FilePath = s
return nil
}
}
//SetClientSaveFile tells the router to use an encrypted leaseset
func SetClientSaveFile(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.save = b
return nil
}
}
//SetClientHost sets the host of the SAMClientForwarder's SAM bridge
func SetClientHost(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.TargetHost = s
return nil
}
}
//SetClientDestination sets the destination to forwarder SAMClientForwarder's to
func SetClientDestination(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.dest = s
return nil
}
}
//SetClientPort sets the port of the SAMClientForwarder's SAM bridge using a string
func SetClientPort(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.TargetPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetClientSAMHost sets the host of the SAMClientForwarder's SAM bridge
func SetClientSAMHost(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.SamHost = s
return nil
}
}
//SetClientSAMPort sets the port of the SAMClientForwarder's SAM bridge using a string
func SetClientSAMPort(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid SAM Port %s; non-number", s)
}
if port < 65536 && port > -1 {
c.SamPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetClientName sets the host of the SAMClientForwarder's SAM bridge
func SetClientName(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.TunName = s
return nil
}
}
//SetClientInLength sets the number of hops inbound
func SetClientInLength(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u < 7 && u >= 0 {
c.inLength = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetClientOutLength sets the number of hops outbound
func SetClientOutLength(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u < 7 && u >= 0 {
c.outLength = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel length")
}
}
//SetClientInVariance sets the variance of a number of hops inbound
func SetClientInVariance(i int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if i < 7 && i > -7 {
c.inVariance = strconv.Itoa(i)
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetClientOutVariance sets the variance of a number of hops outbound
func SetClientOutVariance(i int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if i < 7 && i > -7 {
c.outVariance = strconv.Itoa(i)
return nil
}
return fmt.Errorf("Invalid outbound tunnel variance")
}
}
//SetClientInQuantity sets the inbound tunnel quantity
func SetClientInQuantity(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u <= 16 && u > 0 {
c.inQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel quantity")
}
}
//SetClientOutQuantity sets the outbound tunnel quantity
func SetClientOutQuantity(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u <= 16 && u > 0 {
c.outQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel quantity")
}
}
//SetClientInBackups sets the inbound tunnel backups
func SetClientInBackups(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u < 6 && u >= 0 {
c.inBackupQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel backup quantity")
}
}
//SetClientOutBackups sets the inbound tunnel backups
func SetClientOutBackups(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u < 6 && u >= 0 {
c.outBackupQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel backup quantity")
}
}
//SetClientEncrypt tells the router to use an encrypted leaseset
func SetClientEncrypt(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.encryptLeaseSet = "true"
return nil
}
c.encryptLeaseSet = "false"
return nil
}
}
//SetClientAllowZeroIn tells the tunnel to accept zero-hop peers
func SetClientAllowZeroIn(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.inAllowZeroHop = "true"
return nil
}
c.inAllowZeroHop = "false"
return nil
}
}
//SetClientAllowZeroOut tells the tunnel to accept zero-hop peers
func SetClientAllowZeroOut(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.outAllowZeroHop = "true"
return nil
}
c.outAllowZeroHop = "false"
return nil
}
}
//SetClientCompress tells clients to use compression
func SetClientCompress(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.useCompression = "true"
return nil
}
c.useCompression = "false"
return nil
}
}
//SetClientReduceIdle tells the connection to reduce it's tunnels during extended idle time.
func SetClientReduceIdle(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.reduceIdle = "true"
return nil
}
c.reduceIdle = "false"
return nil
}
}
//SetClientReduceIdleTime sets the time to wait before reducing tunnels to idle levels
func SetClientReduceIdleTime(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.reduceIdleTime = strconv.Itoa(300000)
if u >= 6 {
c.reduceIdleTime = strconv.Itoa((u * 60) * 1000)
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in minutes) %v", u)
}
}
//SetClientReduceIdleTimeMs sets the time to wait before reducing tunnels to idle levels in milliseconds
func SetClientReduceIdleTimeMs(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.reduceIdleTime = strconv.Itoa(300000)
if u >= 300000 {
c.reduceIdleTime = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in milliseconds) %v", u)
}
}
//SetClientReduceIdleQuantity sets minimum number of tunnels to reduce to during idle time
func SetClientReduceIdleQuantity(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if u < 5 {
c.reduceIdleQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid reduce tunnel quantity")
}
}
//SetClientCloseIdle tells the connection to close it's tunnels during extended idle time.
func SetClientCloseIdle(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.closeIdle = "true"
return nil
}
c.closeIdle = "false"
return nil
}
}
//SetClientCloseIdleTime sets the time to wait before closing tunnels to idle levels
func SetClientCloseIdleTime(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.closeIdleTime = strconv.Itoa(300000)
if u >= 6 {
c.closeIdleTime = strconv.Itoa((u * 60) * 1000)
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in minutes) %v", u)
}
}
//SetClientCloseIdleTimeMs sets the time to wait before closing tunnels to idle levels in milliseconds
func SetClientCloseIdleTimeMs(u int) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.closeIdleTime = strconv.Itoa(300000)
if u >= 300000 {
c.closeIdleTime = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in milliseconds) %v", u)
}
}
//SetClientAccessListType tells the system to treat the accessList as a whitelist
func SetClientAccessListType(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if s == "whitelist" {
c.accessListType = "whitelist"
return nil
} else if s == "blacklist" {
c.accessListType = "blacklist"
return nil
} else if s == "none" {
c.accessListType = ""
return nil
} else if s == "" {
c.accessListType = ""
}
return fmt.Errorf("Invalid Access list type(whitelist, blacklist, none)")
}
}
//SetClientAccessList tells the system to treat the accessList as a whitelist
func SetClientAccessList(s []string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if len(s) > 0 {
for _, a := range s {
c.accessList = append(c.accessList, a)
}
return nil
}
return nil
}
}

View File

@@ -1,235 +0,0 @@
package samforwarder
import (
"io"
"log"
"net"
"os"
"path/filepath"
"strings"
)
import (
"github.com/eyedeekay/sam3"
)
// SAMClientForwarder is a tcp proxy that automatically forwards ports to i2p
type SAMClientForwarder struct {
SamHost string
SamPort string
TunName string
TargetHost string
TargetPort string
samConn *sam3.SAM
SamKeys sam3.I2PKeys
connectStream *sam3.StreamSession
dest string
addr sam3.I2PAddr
publishConnection net.Listener
FilePath string
file io.ReadWriter
save bool
// I2CP options
encryptLeaseSet string
LeaseSetKeys *sam3.I2PKeys
inAllowZeroHop string
outAllowZeroHop string
inLength string
outLength string
inQuantity string
outQuantity string
inVariance string
outVariance string
inBackupQuantity string
outBackupQuantity string
useCompression string
closeIdle string
closeIdleTime string
reduceIdle string
reduceIdleTime string
reduceIdleQuantity string
//Streaming Library options
accessListType string
accessList []string
}
//var err error
func (f *SAMClientForwarder) accesslisttype() string {
if f.accessListType == "whitelist" {
return "i2cp.enableAccessList=true"
} else if f.accessListType == "blacklist" {
return "i2cp.enableBlackList=true"
} else if f.accessListType == "none" {
return ""
}
return ""
}
func (f *SAMClientForwarder) accesslist() string {
if f.accessListType != "" && len(f.accessList) > 0 {
r := ""
for _, s := range f.accessList {
r += s + ","
}
return "i2cp.accessList=" + strings.TrimSuffix(r, ",")
}
return ""
}
// Target returns the host:port of the local service you want to forward to i2p
func (f *SAMClientForwarder) Target() string {
return f.TargetHost + ":" + f.TargetPort
}
func (f *SAMClientForwarder) sam() string {
return f.SamHost + ":" + f.SamPort
}
//Base32 returns the base32 address of the local destination
func (f *SAMClientForwarder) Base32() string {
return f.SamKeys.Addr().Base32()
}
//Base64 returns the base64 address of the local destiantion
func (f *SAMClientForwarder) Base64() string {
return f.SamKeys.Addr().Base64()
}
func (f *SAMClientForwarder) forward(conn net.Conn) {
client, err := f.connectStream.DialI2P(f.addr)
if err != nil {
log.Fatalf("Dial failed: %v", err)
}
log.Printf("Connected to localhost %v\n", conn)
go func() {
defer client.Close()
defer conn.Close()
io.Copy(client, conn)
}()
go func() {
defer client.Close()
defer conn.Close()
io.Copy(conn, client)
}()
}
//Serve starts the SAM connection and and forwards the local host:port to i2p
func (f *SAMClientForwarder) Serve(dest string) error {
f.dest = dest
if f.addr, err = f.samConn.Lookup(f.dest); err != nil {
return err
}
if f.connectStream, err = f.samConn.NewStreamSession(f.TunName, f.SamKeys,
[]string{
"inbound.length=" + f.inLength,
"outbound.length=" + f.outLength,
"inbound.lengthVariance=" + f.inVariance,
"outbound.lengthVariance=" + f.outVariance,
"inbound.backupQuantity=" + f.inBackupQuantity,
"outbound.backupQuantity=" + f.outBackupQuantity,
"inbound.quantity=" + f.inQuantity,
"outbound.quantity=" + f.outQuantity,
"inbound.allowZeroHop=" + f.inAllowZeroHop,
"outbound.allowZeroHop=" + f.outAllowZeroHop,
"i2cp.encryptLeaseSet=" + f.encryptLeaseSet,
"i2cp.gzip=" + f.useCompression,
"i2cp.reduceOnIdle=" + f.reduceIdle,
"i2cp.reduceIdleTime=" + f.reduceIdleTime,
"i2cp.reduceQuantity=" + f.reduceIdleQuantity,
"i2cp.closeOnIdle=" + f.closeIdle,
"i2cp.closeIdleTime=" + f.closeIdleTime,
f.accesslisttype(),
f.accesslist(),
}); err != nil {
log.Println("Stream Creation error:", err.Error())
return err
}
log.Println("SAM stream session established.")
for {
conn, err := f.publishConnection.Accept()
if err != nil {
return err
}
log.Println("Forwarding client to i2p address:", f.addr.Base32())
go f.forward(conn)
}
}
//NewSAMClientForwarder makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMClientForwarder(host, port string) (*SAMClientForwarder, error) {
return NewSAMClientForwarderFromOptions(SetClientHost(host), SetClientPort(port))
}
//NewSAMClientForwarderFromOptions makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMClientForwarderFromOptions(opts ...func(*SAMClientForwarder) error) (*SAMClientForwarder, error) {
var s SAMClientForwarder
s.SamHost = "127.0.0.1"
s.SamPort = "7656"
s.FilePath = ""
s.save = false
s.TargetHost = "127.0.0.1"
s.TargetPort = "0"
s.TunName = "samForwarder"
s.inLength = "3"
s.outLength = "3"
s.inQuantity = "8"
s.outQuantity = "8"
s.inVariance = "1"
s.outVariance = "1"
s.inBackupQuantity = "3"
s.outBackupQuantity = "3"
s.inAllowZeroHop = "false"
s.outAllowZeroHop = "false"
s.encryptLeaseSet = "false"
s.useCompression = "true"
s.reduceIdle = "false"
s.reduceIdleTime = "300000"
s.reduceIdleQuantity = "4"
s.closeIdle = "false"
s.closeIdleTime = "300000"
s.dest = "none"
for _, o := range opts {
if err := o(&s); err != nil {
return nil, err
}
}
if s.publishConnection, err = net.Listen("tcp", s.TargetHost+":"+s.TargetPort); err != nil {
return nil, err
}
if s.samConn, err = sam3.NewSAM(s.sam()); err != nil {
return nil, err
}
log.Println("SAM Bridge connection established.")
if s.SamKeys, err = s.samConn.NewKeys(); err != nil {
return nil, err
}
log.Println("Destination keys generated, tunnel name:", s.TunName)
if s.save {
if _, err := os.Stat(filepath.Join(s.FilePath, s.TunName+".i2pkeys")); os.IsNotExist(err) {
s.file, err = os.Create(filepath.Join(s.FilePath, s.TunName+".i2pkeys"))
if err != nil {
return nil, err
}
err = sam3.StoreKeysIncompat(s.SamKeys, s.file)
if err != nil {
return nil, err
}
}
s.file, err = os.Open(filepath.Join(s.FilePath, s.TunName+".i2pkeys"))
if err != nil {
return nil, err
}
s.SamKeys, err = sam3.LoadKeysIncompat(s.file)
if err != nil {
return nil, err
}
}
return &s, nil
}

View File

@@ -1,360 +0,0 @@
package samforwarder
import (
"fmt"
"strconv"
)
//Option is a SAMForwarder Option
type Option func(*SAMForwarder) error
//SetFilePath sets the host of the SAMForwarder's SAM bridge
func SetFilePath(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.FilePath = s
return nil
}
}
//SetType sets the type of the forwarder server
func SetType(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if s == "http" {
c.Type = s
return nil
} else if s == "server" {
c.Type = s
return nil
}
return fmt.Errorf("Invalid server type")
}
}
//SetSaveFile tells the router to use an encrypted leaseset
func SetSaveFile(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.save = b
return nil
}
}
//SetHost sets the host of the SAMForwarder's SAM bridge
func SetHost(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.TargetHost = s
return nil
}
}
//SetPort sets the port of the SAMForwarder's SAM bridge using a string
func SetPort(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.TargetPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetSAMHost sets the host of the SAMForwarder's SAM bridge
func SetSAMHost(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.SamHost = s
return nil
}
}
//SetSAMPort sets the port of the SAMForwarder's SAM bridge using a string
func SetSAMPort(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid SAM Port %s; non-number", s)
}
if port < 65536 && port > -1 {
c.SamPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetName sets the host of the SAMForwarder's SAM bridge
func SetName(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.TunName = s
return nil
}
}
//SetInLength sets the number of hops inbound
func SetInLength(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u < 7 && u >= 0 {
c.inLength = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetOutLength sets the number of hops outbound
func SetOutLength(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u < 7 && u >= 0 {
c.outLength = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel length")
}
}
//SetInVariance sets the variance of a number of hops inbound
func SetInVariance(i int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if i < 7 && i > -7 {
c.inVariance = strconv.Itoa(i)
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetOutVariance sets the variance of a number of hops outbound
func SetOutVariance(i int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if i < 7 && i > -7 {
c.outVariance = strconv.Itoa(i)
return nil
}
return fmt.Errorf("Invalid outbound tunnel variance")
}
}
//SetInQuantity sets the inbound tunnel quantity
func SetInQuantity(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u <= 16 && u > 0 {
c.inQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel quantity")
}
}
//SetOutQuantity sets the outbound tunnel quantity
func SetOutQuantity(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u <= 16 && u > 0 {
c.outQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel quantity")
}
}
//SetInBackups sets the inbound tunnel backups
func SetInBackups(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u < 6 && u >= 0 {
c.inBackupQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid inbound tunnel backup quantity")
}
}
//SetOutBackups sets the inbound tunnel backups
func SetOutBackups(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u < 6 && u >= 0 {
c.outBackupQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid outbound tunnel backup quantity")
}
}
//SetEncrypt tells the router to use an encrypted leaseset
func SetEncrypt(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.encryptLeaseSet = "true"
return nil
}
c.encryptLeaseSet = "false"
return nil
}
}
//SetAllowZeroIn tells the tunnel to accept zero-hop peers
func SetAllowZeroIn(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.inAllowZeroHop = "true"
return nil
}
c.inAllowZeroHop = "false"
return nil
}
}
//SetAllowZeroOut tells the tunnel to accept zero-hop peers
func SetAllowZeroOut(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.outAllowZeroHop = "true"
return nil
}
c.outAllowZeroHop = "false"
return nil
}
}
//SetCompress tells clients to use compression
func SetCompress(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.useCompression = "true"
return nil
}
c.useCompression = "false"
return nil
}
}
//SetReduceIdle tells the connection to reduce it's tunnels during extended idle time.
func SetReduceIdle(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.reduceIdle = "true"
return nil
}
c.reduceIdle = "false"
return nil
}
}
//SetReduceIdleTime sets the time to wait before reducing tunnels to idle levels
func SetReduceIdleTime(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.reduceIdleTime = strconv.Itoa(300000)
if u >= 6 {
c.reduceIdleTime = strconv.Itoa((u * 60) * 1000)
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in minutes) %v", u)
}
}
//SetReduceIdleTimeMs sets the time to wait before reducing tunnels to idle levels in milliseconds
func SetReduceIdleTimeMs(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.reduceIdleTime = strconv.Itoa(300000)
if u >= 300000 {
c.reduceIdleTime = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in milliseconds) %v", u)
}
}
//SetReduceIdleQuantity sets minimum number of tunnels to reduce to during idle time
func SetReduceIdleQuantity(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if u < 5 {
c.reduceIdleQuantity = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid reduce tunnel quantity")
}
}
//SetCloseIdle tells the connection to close it's tunnels during extended idle time.
func SetCloseIdle(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.closeIdle = "true"
return nil
}
c.closeIdle = "false"
return nil
}
}
//SetCloseIdleTime sets the time to wait before closing tunnels to idle levels
func SetCloseIdleTime(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.closeIdleTime = strconv.Itoa(300000)
if u >= 6 {
c.closeIdleTime = strconv.Itoa((u * 60) * 1000)
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in minutes) %v", u)
}
}
//SetCloseIdleTimeMs sets the time to wait before closing tunnels to idle levels in milliseconds
func SetCloseIdleTimeMs(u int) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.closeIdleTime = strconv.Itoa(300000)
if u >= 300000 {
c.closeIdleTime = strconv.Itoa(u)
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in milliseconds) %v", u)
}
}
//SetAccessListType tells the system to treat the accessList as a whitelist
func SetAccessListType(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if s == "whitelist" {
c.accessListType = "whitelist"
return nil
} else if s == "blacklist" {
c.accessListType = "blacklist"
return nil
} else if s == "none" {
c.accessListType = ""
return nil
} else if s == "" {
c.accessListType = ""
}
return fmt.Errorf("Invalid Access list type(whitelist, blacklist, none)")
}
}
//SetAccessList tells the system to treat the accessList as a whitelist
func SetAccessList(s []string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if len(s) > 0 {
for _, a := range s {
c.accessList = append(c.accessList, a)
}
return nil
}
return nil
}
}
//SetTargetForPort sets the port of the SAMForwarder's SAM bridge using a string
/*func SetTargetForPort443(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.TargetForPort443 = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
*/

View File

@@ -1,277 +0,0 @@
package samforwarder
import (
"bufio"
"io"
"log"
"net"
"net/http"
"net/http/httputil"
"os"
"path/filepath"
"strings"
)
import (
"github.com/eyedeekay/sam3"
)
//SAMForwarder is a structure which automatically configured the forwarding of
//a local service to i2p over the SAM API.
type SAMForwarder struct {
SamHost string
SamPort string
TunName string
TargetHost string
TargetPort string
samConn *sam3.SAM
SamKeys sam3.I2PKeys
publishStream *sam3.StreamSession
publishListen *sam3.StreamListener
publishConnection net.Conn
FilePath string
file io.ReadWriter
save bool
Type string
// I2CP options
encryptLeaseSet string
LeaseSetKeys *sam3.I2PKeys
inAllowZeroHop string
outAllowZeroHop string
inLength string
outLength string
inQuantity string
outQuantity string
inVariance string
outVariance string
inBackupQuantity string
outBackupQuantity string
useCompression string
closeIdle string
closeIdleTime string
reduceIdle string
reduceIdleTime string
reduceIdleQuantity string
//Streaming Library options
accessListType string
accessList []string
}
var err error
/*func (f *SAMForwarder) targetForPort443() string {
if f.TargetForPort443 != "" {
return "targetForPort.4443=" + f.TargetHost + ":" + f.TargetForPort443
}
return ""
}*/
func (f *SAMForwarder) accesslisttype() string {
if f.accessListType == "whitelist" {
return "i2cp.enableAccessList=true"
} else if f.accessListType == "blacklist" {
return "i2cp.enableBlackList=true"
} else if f.accessListType == "none" {
return ""
}
return ""
}
func (f *SAMForwarder) accesslist() string {
if f.accessListType != "" && len(f.accessList) > 0 {
r := ""
for _, s := range f.accessList {
r += s + ","
}
return "i2cp.accessList=" + strings.TrimSuffix(r, ",")
}
return ""
}
// Target returns the host:port of the local service you want to forward to i2p
func (f *SAMForwarder) Target() string {
return f.TargetHost + ":" + f.TargetPort
}
func (f *SAMForwarder) sam() string {
return f.SamHost + ":" + f.SamPort
}
func (f *SAMForwarder) HTTPRequestBytes(conn *sam3.SAMConn) ([]byte, error) {
var request *http.Request
var retrequest []byte
var err error
request, err = http.ReadRequest(bufio.NewReader(conn))
if err != nil {
return nil, err
}
dest := conn.RemoteAddr().(sam3.I2PAddr)
log.Printf("Adding headers to http connection\n\tX-I2p-Dest-Base64=%s\n\tX-I2p-Dest-Base32=%s\n\tX-I2p-Dest-Hash=%s",
dest.Base64(), dest.Base32(), dest.DestHash().String())
request.Header.Add("X-I2p-Dest-Base64", dest.Base64())
request.Header.Add("X-I2p-Dest-Base32", dest.Base32())
request.Header.Add("X-I2p-Dest-Hash", dest.DestHash().String())
if retrequest, err = httputil.DumpRequest(request, true); err != nil {
return nil, err
}
return retrequest, nil
}
func (f *SAMForwarder) forward(conn *sam3.SAMConn) { //(conn net.Conn) {
var err error
client, err := net.Dial("tcp", f.Target())
if err != nil {
log.Fatalf("Dial failed: %v", err)
}
go func() {
defer client.Close()
defer conn.Close()
if f.Type == "http" {
if b, e := f.HTTPRequestBytes(conn); e == nil {
client.Write(b)
} else {
log.Println("Error: ", b, e)
}
} else {
io.Copy(client, conn)
}
}()
go func() {
defer client.Close()
defer conn.Close()
if f.Type == "http" {
io.Copy(conn, client)
} else {
io.Copy(conn, client)
}
}()
}
//Base32 returns the base32 address where the local service is being forwarded
func (f *SAMForwarder) Base32() string {
return f.SamKeys.Addr().Base32()
}
//Base64 returns the base64 address where the local service is being forwarded
func (f *SAMForwarder) Base64() string {
return f.SamKeys.Addr().Base64()
}
//Serve starts the SAM connection and and forwards the local host:port to i2p
func (f *SAMForwarder) Serve() error {
if f.publishStream, err = f.samConn.NewStreamSession(f.TunName, f.SamKeys,
[]string{
//f.targetForPort443(),
"inbound.length=" + f.inLength,
"outbound.length=" + f.outLength,
"inbound.lengthVariance=" + f.inVariance,
"outbound.lengthVariance=" + f.outVariance,
"inbound.backupQuantity=" + f.inBackupQuantity,
"outbound.backupQuantity=" + f.outBackupQuantity,
"inbound.quantity=" + f.inQuantity,
"outbound.quantity=" + f.outQuantity,
"inbound.allowZeroHop=" + f.inAllowZeroHop,
"outbound.allowZeroHop=" + f.outAllowZeroHop,
"i2cp.encryptLeaseSet=" + f.encryptLeaseSet,
"i2cp.gzip=" + f.useCompression,
"i2cp.reduceOnIdle=" + f.reduceIdle,
"i2cp.reduceIdleTime=" + f.reduceIdleTime,
"i2cp.reduceQuantity=" + f.reduceIdleQuantity,
"i2cp.closeOnIdle=" + f.closeIdle,
"i2cp.closeIdleTime=" + f.closeIdleTime,
f.accesslisttype(),
f.accesslist(),
}); err != nil {
log.Println("Stream Creation error:", err.Error())
return err
}
log.Println("SAM stream session established.")
if f.publishListen, err = f.publishStream.Listen(); err != nil {
return err
}
log.Println("Starting Listener.")
b := string(f.SamKeys.Addr().Base32())
log.Println("SAM Listener created,", b)
for {
conn, err := f.publishListen.AcceptI2P()
if err != nil {
log.Fatalf("ERROR: failed to accept listener: %v", err)
}
log.Printf("Accepted connection %v\n", conn)
go f.forward(conn)
}
}
//NewSAMForwarder makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMForwarder(host, port string) (*SAMForwarder, error) {
return NewSAMForwarderFromOptions(SetHost(host), SetPort(port))
}
//NewSAMForwarderFromOptions makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMForwarderFromOptions(opts ...func(*SAMForwarder) error) (*SAMForwarder, error) {
var s SAMForwarder
s.SamHost = "127.0.0.1"
s.SamPort = "7656"
s.FilePath = ""
s.save = false
s.TargetHost = "127.0.0.1"
s.TargetPort = "8081"
s.TunName = "samForwarder"
s.inLength = "3"
s.outLength = "3"
s.inQuantity = "8"
s.outQuantity = "8"
s.inVariance = "1"
s.outVariance = "1"
s.inBackupQuantity = "3"
s.outBackupQuantity = "3"
s.inAllowZeroHop = "false"
s.outAllowZeroHop = "false"
s.encryptLeaseSet = "false"
s.useCompression = "true"
s.reduceIdle = "false"
s.reduceIdleTime = "15"
s.reduceIdleQuantity = "4"
s.closeIdle = "false"
s.closeIdleTime = "300000"
for _, o := range opts {
if err := o(&s); err != nil {
return nil, err
}
}
if s.samConn, err = sam3.NewSAM(s.sam()); err != nil {
return nil, err
}
log.Println("SAM Bridge connection established.")
if s.SamKeys, err = s.samConn.NewKeys(); err != nil {
return nil, err
}
log.Println("Destination keys generated, tunnel name:", s.TunName)
if s.save {
if _, err := os.Stat(filepath.Join(s.FilePath, s.TunName+".i2pkeys")); os.IsNotExist(err) {
s.file, err = os.Create(filepath.Join(s.FilePath, s.TunName+".i2pkeys"))
if err != nil {
return nil, err
}
err = sam3.StoreKeysIncompat(s.SamKeys, s.file)
if err != nil {
return nil, err
}
}
s.file, err = os.Open(filepath.Join(s.FilePath, s.TunName+".i2pkeys"))
if err != nil {
return nil, err
}
s.SamKeys, err = sam3.LoadKeysIncompat(s.file)
if err != nil {
return nil, err
}
}
return &s, nil
}

26
go.mod Normal file
View File

@@ -0,0 +1,26 @@
module github.com/eyedeekay/sam-forwarder
go 1.12
require (
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e
github.com/cryptix/goSam v0.1.0 // indirect
github.com/eyedeekay/eephttpd v0.0.0-20190903000420-52f5a8485a4e
github.com/eyedeekay/httptunnel v0.0.0-20190831071439-0ff3d5f798fb
github.com/eyedeekay/i2pdig v0.0.0-20180718204453-a67cb46e2e5f // indirect
github.com/eyedeekay/outproxy v0.0.0-20190908174238-22bd71d43733
github.com/eyedeekay/portcheck v0.0.0-20190218044454-bb8718669680
github.com/eyedeekay/sam3 v0.32.1
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69
github.com/justinas/nosurf v0.0.0-20190416172904-05988550ea18
github.com/kr/pretty v0.2.0 // indirect
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/spf13/pflag v1.0.3 // indirect
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26
github.com/zserge/lorca v0.1.8
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb
gitlab.com/opennota/wd v0.0.0-20191124020556-236695b0ea63 // indirect
)

85
go.sum Normal file
View File

@@ -0,0 +1,85 @@
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce h1:4VyRNGOpNgP9ioTYZ7ah3x8C28I7wsMt4Ao9nTXv2ec=
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce/go.mod h1:TIbCAHgttUfOKudw59Il7Z0XIlitzo228/mtwMe4vPM=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e h1:2q8XPjAYhXX8H71AoAPdgBrCUA3HPhC4ax8XHrTsY6I=
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e/go.mod h1:y80zLCg0QS5u3fJKeF2rwpezcyZuCpZpbFcWv6Pn98w=
github.com/cryptix/go v1.3.1/go.mod h1:mFQotm9rTzptzvNjJM+1vSIDa/rVOVqMu0889GIXg70=
github.com/cryptix/goSam v0.1.0/go.mod h1:7ewkjhXT8V5RG07pvWUOHHtMahvGbeKlEv8ukUyRiTA=
github.com/d5/tengo v1.24.3 h1:wp44VW7fdfzMzIDT19tT5uNeGnm2UMd6s3TLAahrwSU=
github.com/d5/tengo v1.24.3/go.mod h1:VhLq8Q2QFhCIJO3NhvM934qOThykMqJi9y9Siqd1ocQ=
github.com/eyedeekay/eephttpd v0.0.0-20190903000420-52f5a8485a4e h1:YizBXWVO0QN/1vkcdXXGenBS0bJAHgJcG+2WO22im0Y=
github.com/eyedeekay/eephttpd v0.0.0-20190903000420-52f5a8485a4e/go.mod h1:wFPQsNBnY95LkuujFEZARo7slafRwoF0D97FFHBoZro=
github.com/eyedeekay/goSam v0.1.1-0.20190814204230-d4c9b8c57dd6 h1:+5eM/MhjGMWCGQCCqn9pb1bmvoRewweWhOaE6fA7kZ0=
github.com/eyedeekay/goSam v0.1.1-0.20190814204230-d4c9b8c57dd6/go.mod h1:kGTfZrncJ4CwMX3d1qA6bcMJTOcuTbOqgWg7WrFNAQ0=
github.com/eyedeekay/httptunnel v0.0.0-20190831065052-9eab288b8a82/go.mod h1:VeXBZz04xj4eUGAcD8ygn2WFxY/dAvRbSNYMWoDzMxc=
github.com/eyedeekay/httptunnel v0.0.0-20190831071439-0ff3d5f798fb h1:jxY4AjQDgkeG2WBop17iJrKcwulVF+fOakOWSiIVcwY=
github.com/eyedeekay/httptunnel v0.0.0-20190831071439-0ff3d5f798fb/go.mod h1:SnCAM9CskhwSFkzDfh+H5yNTbvhcTeKekkuX0ejCcSk=
github.com/eyedeekay/i2pdig v0.0.0-20180718204453-a67cb46e2e5f/go.mod h1:Zp2JSsndmRykjDGbNS5QHnCYCLnOeYFvwuZFwsATz8k=
github.com/eyedeekay/outproxy v0.0.0-20190908174238-22bd71d43733 h1:bm9QcH6cMUUKQ9cOiTgTVLaU9FwhvwecxCSZepKTMcU=
github.com/eyedeekay/outproxy v0.0.0-20190908174238-22bd71d43733/go.mod h1:jUBr6XRbiuUBe/sSbVdO5upU4mp8842bdpXDsQY54Rc=
github.com/eyedeekay/portcheck v0.0.0-20190218044454-bb8718669680 h1:wZxtUXCp5cOF5gB6PGeUny7ljGFcK6YKFfU7Sf8JBLc=
github.com/eyedeekay/portcheck v0.0.0-20190218044454-bb8718669680/go.mod h1:8VVIH19/CU2VFJB8P6e58Mo9nvDqqKgllS0oQY3F83U=
github.com/eyedeekay/ramp v0.0.0-20190429201811-305b382042ab h1:EfTRHxGSbiaEyxNzvKRBWVIDw3mD8xXGxj4gvwFzY7Q=
github.com/eyedeekay/ramp v0.0.0-20190429201811-305b382042ab/go.mod h1:h7mvUAMgZ/rtRDUOkvKTK+8LnDMeUhJSoa5EPdB51fc=
github.com/eyedeekay/sam-forwarder v0.0.0-20190814201550-7c0d7cb0d56c/go.mod h1:Ptrm1d4a3KC5/cN264Gn6OntYOmcuJ8Pkyd7+hA01gw=
github.com/eyedeekay/sam-forwarder v0.0.0-20190831071254-d67c0c0e311f/go.mod h1:u4K8aGwSIuMSQ/OzsH7zkshnEvCQgUupfexLXZIjsDI=
github.com/eyedeekay/sam-forwarder v0.0.0-20190905212604-029317222e15/go.mod h1:kFP6jkqHUTGGW/nMUZLnRonkPWE9fyEc8/eSU1CqTFg=
github.com/eyedeekay/sam3 v0.0.0-20190613034117-99ad6522ebe3/go.mod h1:Vrxh+71E3HVYqyRlT5Jg+E26sSuu8UNTLB4p8qyT408=
github.com/eyedeekay/sam3 v0.0.0-20190730185140-f8d54526ea25/go.mod h1:Y3igFVzN4ybqkkpfUWULGhw7WRp8lieq0ORXbLBbcZM=
github.com/eyedeekay/sam3 v0.32.1 h1:xaquh9Sxyuxh0SKyv3Gh6wXcZ5QAfWC4Iz4IsjVSESk=
github.com/eyedeekay/sam3 v0.32.1/go.mod h1:Y3igFVzN4ybqkkpfUWULGhw7WRp8lieq0ORXbLBbcZM=
github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.7.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69 h1:7xsUJsB2NrdcttQPa7JLEaGzvdbk7KvfrjgHZXOQRo0=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo=
github.com/justinas/nosurf v0.0.0-20190416172904-05988550ea18 h1:ci3v0mUqcCewO25ntt7hprt2ZMNA0AWI6s6qV0rSpc0=
github.com/justinas/nosurf v0.0.0-20190416172904-05988550ea18/go.mod h1:Aucr5I5chr4OCuuVB4LTuHVrKHBuyRSo7vM2hqrcb7E=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0/go.mod h1:P6fDJzlxN+cWYR09KbE9/ta+Y6JofX9tAUhJpWkWPaM=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26 h1:E0lEWrifmR0ACbGf5PLji1XbW6rtIXLHCXO/YOqi0AE=
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26/go.mod h1:TQpdgg7I9+PFIkatlx/dnZyZb4iZyCUx1HJj4rXi3+E=
github.com/zserge/lorca v0.1.8 h1:gZwyvesmaoGCwxF5NssI6pdydXkCVHOoHw2nks/PBRs=
github.com/zserge/lorca v0.1.8/go.mod h1:gTrVdXKyWxNhc8aUb1Uu3s0mY343arR1T6jUtxmBxR8=
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb h1:zVjnyZIM7UtkG3dNckiudIm+TUHkZqi5xlVQPd3J6/c=
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
gitlab.com/golang-commonmark/html v0.0.0-20180917080848-cfaf75183c4a h1:Ax7kdHNICZiIeFpmevmaEWb0Ae3BUj3zCTKhZHZ+zd0=
gitlab.com/golang-commonmark/html v0.0.0-20180917080848-cfaf75183c4a/go.mod h1:JT4uoTz0tfPoyVH88GZoWDNm5NHJI2VbUW+eyPClueI=
gitlab.com/golang-commonmark/linkify v0.0.0-20180917065525-c22b7bdb1179 h1:rbON2KwBnWuFMlSHM8LELLlwroDRZw6xv0e6il6e5dk=
gitlab.com/golang-commonmark/linkify v0.0.0-20180917065525-c22b7bdb1179/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
gitlab.com/golang-commonmark/markdown v0.0.0-20181102083822-772775880e1f h1:jwXy/CsM4xS2aoiF2fHAlukmInWhd2TlWB+HDCyvzKc=
gitlab.com/golang-commonmark/markdown v0.0.0-20181102083822-772775880e1f/go.mod h1:SIHlEr9462fpIfTrVWf3GqQDxnA65Vm3BMMsUtuA6W0=
gitlab.com/golang-commonmark/mdurl v0.0.0-20180912090424-e5bce34c34f2 h1:wD/sPUgx2QJFPTyXZpJnLaROolfeKuruh06U4pRV0WY=
gitlab.com/golang-commonmark/mdurl v0.0.0-20180912090424-e5bce34c34f2/go.mod h1:wQk4rLkWrdOPjUAtqJRJ10hIlseLSVYWP95PLrjDF9s=
gitlab.com/golang-commonmark/puny v0.0.0-20180912090636-2cd490539afe h1:5kUPFAF52umOUPH12MuNUmyVTseJRNBftDl/KfsvX3I=
gitlab.com/golang-commonmark/puny v0.0.0-20180912090636-2cd490539afe/go.mod h1:P9LSM1KVzrIstFgUaveuwiAm8PK5VTB3yJEU8kqlbrU=
gitlab.com/opennota/wd v0.0.0-20191124020556-236695b0ea63/go.mod h1:n0SNS6rmmsb705EuaYk2RDZyy+pcmwEAuwQkTOOjsu8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190830142957-1e83adbbebd0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190830223141-573d9926052a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

24
gui/nostatic.go Normal file
View File

@@ -0,0 +1,24 @@
// +build nostatic
package gui
import (
"github.com/eyedeekay/sam-forwarder/interface"
"github.com/zserge/webview"
)
func LaunchUI(s samtunnel.WebUI) (webview.WebView, error) {
if s.UseWebUI() == true {
settings := webview.Settings{
Title: s.Title(),
URL: s.URL(),
Height: s.Height(),
Width: s.Width(),
Resizable: s.Resizable(),
Debug: true,
}
view := webview.New(settings)
return view, nil
}
return nil, nil
}

19
gui/static.go Normal file
View File

@@ -0,0 +1,19 @@
// +build !nostatic
package gui
import (
"github.com/eyedeekay/sam-forwarder/interface"
"github.com/zserge/lorca"
)
var USER = ""
func LaunchUI(s samtunnel.WebUI) (lorca.UI, error) {
if s.UseWebUI() == true {
if lorca.LocateChrome() != "" {
return lorca.New(s.URL(), s.Title(), s.Width(), s.Height())
}
}
return nil, nil
}

113
handler/login.go Normal file
View File

@@ -0,0 +1,113 @@
package samtunnelhandler
import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"time"
)
// Create a struct that models the structure of a user, both in the request body, and in the DB
type Credentials struct {
Password string `json:"password"`
Username string `json:"username"`
}
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return nil, err
}
return b, nil
}
func GenerateRandomString(s int) (string, error) {
b, err := GenerateRandomBytes(s)
return base64.URLEncoding.EncodeToString(b), err
}
func (m *TunnelHandlerMux) Signin(w http.ResponseWriter, r *http.Request) {
var creds Credentials
err := json.NewDecoder(r.Body).Decode(&creds)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
if creds.Username != m.user {
w.WriteHeader(http.StatusUnauthorized)
return
}
if creds.Password != m.password {
w.WriteHeader(http.StatusUnauthorized)
return
}
m.sessionToken, err = GenerateRandomString(32)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
http.SetCookie(w, &http.Cookie{
Name: "session_token",
Value: m.sessionToken,
Expires: time.Now().Add(10 * time.Minute),
})
}
func (m *TunnelHandlerMux) Home(w http.ResponseWriter, r *http.Request) {
if m.CheckCookie(w, r) == false {
return
}
// fmt.Fprintf(w, "URL PATH", r.URL.Path)
if r.URL.Path == "/" {
http.Redirect(w, r, "/index.html", 301)
fmt.Fprintf(w, "redirecting to index.html")
return
}
r2, err := http.NewRequest("GET", r.URL.Path+"/color", r.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "<!DOCTYPE html>\n")
fmt.Fprintf(w, "<html>\n")
fmt.Fprintf(w, "<head>\n")
fmt.Fprintf(w, " <title>")
fmt.Fprintf(w, "samcatd")
fmt.Fprintf(w, " </title>")
fmt.Fprintf(w, " <link rel=\"stylesheet\" href=\"/styles.css\">")
fmt.Fprintf(w, "</head>\n")
fmt.Fprintf(w, " <body>\n")
fmt.Fprintf(w, " <h1>\n")
w.Write([]byte(fmt.Sprintf(" <a href=\"/index.html\">Welcome %s! you are serving %d tunnels. </a>\n", m.user, len(m.tunnels))))
//fmt.Fprintf(w, "")
fmt.Fprintf(w, " </h1>\n")
fmt.Fprintf(w, " <div id=\"toggleall\" class=\"global control\">\n")
fmt.Fprintf(w, " <a href=\"#\" onclick=\"toggle_visibility_class('%s');\">Show/Hide %s</a>\n", "prop", "all")
fmt.Fprintf(w, " </div>\n")
for _, tunnel := range m.Tunnels() {
tunnel.ServeHTTP(w, r2)
}
fmt.Fprintf(w, " <script src=\"/scripts.js\"></script>\n")
fmt.Fprintf(w, " </body>\n")
fmt.Fprintf(w, "</html>\n")
}
func (m *TunnelHandlerMux) CSS(w http.ResponseWriter, r *http.Request) {
if m.CheckCookie(w, r) == false {
return
}
w.Header().Add("Content-Type", "text/css")
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("%s\n", m.cssString)))
}
func (m *TunnelHandlerMux) JS(w http.ResponseWriter, r *http.Request) {
if m.CheckCookie(w, r) == false {
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("%s\n", m.jsString)))
}

121
handler/mux.go Normal file
View File

@@ -0,0 +1,121 @@
package samtunnelhandler
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
type TunnelHandlerMux struct {
http.Server
pagenames []string
tunnels []*TunnelHandler
user string
password string
sessionToken string
cssString string
jsString string
}
func (m *TunnelHandlerMux) ListenAndServe() {
m.Server.ListenAndServe()
}
func (m *TunnelHandlerMux) CheckCookie(w http.ResponseWriter, r *http.Request) bool {
if m.password != "" {
if m.sessionToken == "" {
w.WriteHeader(http.StatusUnauthorized)
return false
}
c, err := r.Cookie("session_token")
if err != nil {
if err == http.ErrNoCookie {
w.WriteHeader(http.StatusUnauthorized)
return false
}
w.WriteHeader(http.StatusBadRequest)
return false
}
if m.sessionToken != c.Value {
w.WriteHeader(http.StatusUnauthorized)
return false
}
}
return true
}
func (m *TunnelHandlerMux) HandlerWrapper(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if m.CheckCookie(w, r) == false {
return
}
if !strings.HasSuffix(r.URL.Path, "color") {
h.ServeHTTP(w, r)
} else {
m.ColorHeader(h, r, w)
}
})
}
func (t *TunnelHandlerMux) Tunnels() []*TunnelHandler {
return t.tunnels
}
func (m *TunnelHandlerMux) Append(v *TunnelHandler) *TunnelHandlerMux {
if m == nil {
return m
}
for _, prev := range m.tunnels {
if v.ID() == prev.ID() {
log.Printf("v.ID() found, %s == %s", v.ID(), prev.ID())
return m
}
}
log.Printf("Adding tunnel ID: %s", v.ID())
m.tunnels = append(m.tunnels, v)
Handler := m.Handler.(*http.ServeMux)
Handler.Handle(fmt.Sprintf("/%d", len(m.tunnels)), m.HandlerWrapper(v))
Handler.Handle(fmt.Sprintf("/%s", v.ID()), m.HandlerWrapper(v))
Handler.Handle(fmt.Sprintf("/%d/color", len(m.tunnels)), m.HandlerWrapper(v))
Handler.Handle(fmt.Sprintf("/%s/color", v.ID()), m.HandlerWrapper(v))
m.Handler = Handler
return m
}
func ReadFile(filename string) (string, error) {
r, e := ioutil.ReadFile(filename)
return string(r), e
}
func NewTunnelHandlerMux(host, port, user, password, css, javascript string) *TunnelHandlerMux {
var m TunnelHandlerMux
m.Addr = host + ":" + port
Handler := http.NewServeMux()
m.pagenames = []string{"index.html", "index", ""}
m.user = user
m.password = password
m.sessionToken = ""
m.tunnels = []*TunnelHandler{}
var err error
m.cssString, err = ReadFile(css)
if err != nil {
m.cssString = DefaultCSS()
}
m.jsString, err = ReadFile(javascript)
if err != nil {
m.jsString = DefaultJS()
}
for _, v := range m.pagenames {
Handler.HandleFunc(fmt.Sprintf("/%s", v), m.Home)
}
Handler.HandleFunc("/styles.css", m.CSS)
Handler.HandleFunc("/scripts.js", m.JS)
if m.password != "" {
Handler.HandleFunc("/login", m.Signin)
}
m.Handler = Handler
return &m
}

260
handler/pages.go Normal file
View File

@@ -0,0 +1,260 @@
package samtunnelhandler
import (
"fmt"
"net/http"
"strings"
)
func DefaultCSS() string {
return `.server {
width: 63%;
min-height: 15%;
background-color: #9DABD5;
float: left;
overflow-wrap: break-word;
}
.client {
width: 63%;
min-height: 15%;
background-color: #2D4470;
float: left;
overflow-wrap: break-word;
}
.tcpclient {
width: 63%;
min-height: 15%;
background-color: #2D4470;
float: left;
overflow-wrap: break-word;
}
.http {
width: 63%;
min-height: 15%;
background-color: #00ffff;
float: left;
overflow-wrap: break-word;
}
.httpclient {
width: 63%;
min-height: 15%;
background-color: #709fa6;
float: left;
overflow-wrap: break-word;
}
.udpserver {
width: 63%;
min-height: 15%;
background-color: #265ea7;
float: left;
overflow-wrap: break-word;
}
.outproxy {
width: 63%;
min-height: 15%;
background-color: #265ea7;
float: left;
overflow-wrap: break-word;
}
.outproxyhttp {
width: 63%;
min-height: 15%;
background-color: #265ea7;
float: left;
overflow-wrap: break-word;
}
.udpclient {
width: 63%;
min-height: 15%;
background-color: #222187;
float: left;
overflow-wrap: break-word;
}
.vpnserver {
width: 63%;
min-height: 15%;
background-color: #265ea7;
float: left;
overflow-wrap: break-word;
}
.vpnclient {
width: 63%;
min-height: 15%;
background-color: #222187;
float: left;
overflow-wrap: break-word;
}
.TunName {
font-weight: bold;
}
.panel {
width: 33%;
float: right;
}
.prop {
}
.prop:hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
}
.global {
background-color: #00ffff;
}
body {
background-color: #9e9e9e;
color: #070425;
font-family: "monospace";
font-size: 1rem;
}
a {
color: #080808;
}
h1 {
background-color: #9e9e9e;
}
span {
float: left;
display: inline;
}
textarea {
display: inline-block;
width: 100%;
resize: none;
height: 1rem;
float: right;
display: inline;
}
.linkstyle {
align-items: normal;
background-color: rgba(0,0,0,0);
border-color: rgb(0, 0, 238);
border-style: none;
box-sizing: content-box;
color: rgb(0, 0, 238);
cursor: pointer;
font: inherit;
height: auto;
display: inline;
padding: 0;
perspective-origin: 0 0;
text-align: start;
text-decoration: underline;
transform-origin: 0 0;
width: auto;
-moz-appearance: none;
-webkit-logical-height: 1em; /* Chrome ignores auto, so we have to use this hack to set the correct height */
-webkit-logical-width: auto; /* Chrome ignores auto, but here for completeness */
}
@supports (-moz-appearance:none) { /* Mozilla-only */
.linkstyle::-moz-focus-inner { /* reset any predefined properties */
border: none;
padding: 0;
}
.linkstyle:focus { /* add outline to focus pseudo-class */
outline-style: dotted;
outline-width: 1px;
}
}
`
}
func DefaultJS() string {
return `function toggle_visibility_id(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
function toggle_visibility_class(id) {
var elist = document.getElementsByClassName(id)
for (let e of elist) {
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
var tlist = document.getElementsByClassName("TunName")
for (let t of tlist) {
t.style.display = 'block';
}
var clist = document.getElementsByClassName("control")
for (let c of clist) {
c.style.display = 'block';
}
var slist = document.getElementsByClassName("status")
for (let s of slist) {
s.style.display = 'block';
}
}
toggle_visibility_class("prop")
`
}
func (t *TunnelHandler) ColorSpan(shortid string) string {
r := fmt.Sprintf(" <span id=\"toggle%s\" class=\"control\">\n", t.SAMTunnel.ID())
r += fmt.Sprintf(" <a href=\"#\" onclick=\"toggle_visibility_class('%s');\"> Show/Hide %s</a><br>\n", t.SAMTunnel.ID(), t.SAMTunnel.ID())
r += fmt.Sprintf(" <a href=\"/%s/color\">Tunnel page</a>\n", t.SAMTunnel.ID())
r += fmt.Sprintf(" </span>\n")
return r
}
func (t *TunnelHandler) ColorForm(shortid, tuntype string) string {
r := fmt.Sprintf(" </div>\n\n")
r += fmt.Sprintf(" <div id=\"%s\" class=\"%s control panel\" >", shortid+".control", tuntype)
r += fmt.Sprintf(" <form class=\"linkstyle\" name=\"start\" action=\"/%s\" method=\"post\">", shortid)
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"hidden\" value=\"start\" name=\"action\" />")
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"submit\" value=\".[START]\">")
r += fmt.Sprintf(" </form>")
r += fmt.Sprintf(" <form class=\"linkstyle\" name=\"stop\" action=\"/%s\" method=\"post\">", shortid)
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"hidden\" value=\"stop\" name=\"action\" />")
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"submit\" value=\".[STOP].\">")
r += fmt.Sprintf(" </form>")
r += fmt.Sprintf(" <form class=\"linkstyle\" name=\"restart\" action=\"/%s\" method=\"post\">", shortid)
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"hidden\" value=\"restart\" name=\"action\" />")
r += fmt.Sprintf(" <input class=\"linkstyle\" type=\"submit\" value=\"[RESTART].\">")
r += fmt.Sprintf(" </form>")
r += fmt.Sprintf(" <div id=\"%s.status\" class=\"%s status\">.[STATUS].</div>", shortid, shortid)
r += fmt.Sprintf(" </div>\n\n")
return r
}
func (t *TunnelHandler) ColorWrap(longid, shortid, key, tuntype, prop, value string) string {
r := fmt.Sprintf(" <div id=\"%s\" class=\"%s %s %s %s\" >\n", longid, shortid, key, tuntype, prop)
r += fmt.Sprintf(" <span id=\"%s\" class=\"key\">%s</span>=", longid, key)
r += fmt.Sprintf(" <textarea id=\"%s\" rows=\"1\" class=\"value\">%s</textarea>\n", longid, value)
r += fmt.Sprintf(" </div>\n\n")
return r
}
func (t *TunnelHandler) ColorDiv(shortid, tuntype string) string {
return fmt.Sprintf(" <div id=\"%s\" class=\"%s\" >", t.SAMTunnel.ID(), t.SAMTunnel.GetType())
}
func (m *TunnelHandlerMux) ColorHeader(h http.Handler, r *http.Request, w http.ResponseWriter) {
if !strings.HasSuffix(r.URL.Path, "color") {
h.ServeHTTP(w, r)
} else {
fmt.Fprintf(w, "<!DOCTYPE html>\n")
fmt.Fprintf(w, "<html>\n")
fmt.Fprintf(w, "<head>\n")
fmt.Fprintf(w, " <link rel=\"stylesheet\" href=\"/styles.css\">")
fmt.Fprintf(w, "</head>\n")
fmt.Fprintf(w, "<body>\n")
fmt.Fprintf(w, "<h1>\n")
w.Write([]byte(fmt.Sprintf("<a href=\"/index.html\">Welcome %s! you are serving %d tunnels. </a>\n", m.user, len(m.tunnels))))
fmt.Fprintf(w, "</h1>\n")
fmt.Fprintf(w, " <div id=\"toggleall\" class=\"global control\">\n")
fmt.Fprintf(w, " <a href=\"#\" onclick=\"toggle_visibility_class('%s');\">Show/Hide %s</a>\n", "prop", "all")
fmt.Fprintf(w, " </div>\n")
h.ServeHTTP(w, r)
fmt.Fprintf(w, " <script src=\"/scripts.js\"></script>\n")
fmt.Fprintf(w, "</body>\n")
fmt.Fprintf(w, "</html>\n")
}
}

126
handler/tunnelhandler.go Normal file
View File

@@ -0,0 +1,126 @@
package samtunnelhandler
import (
"fmt"
"net/http"
"sort"
"strings"
)
import (
"github.com/eyedeekay/sam-forwarder/interface"
)
type TunnelHandler struct {
samtunnel.SAMTunnel
}
func (t *TunnelHandler) Printdivf(id, key, value string, rw http.ResponseWriter, req *http.Request) {
if key == "" || value == "" {
return
}
ID := t.SAMTunnel.ID()
if id != "" {
ID = t.SAMTunnel.ID() + "." + id
}
prop := ""
if key != "TunName" {
prop = "prop"
}
fmt.Fprintf(rw, t.ColorWrap(ID, t.SAMTunnel.ID(), key, t.SAMTunnel.GetType(), prop, value))
}
func (t *TunnelHandler) Printf(id, key, value string, rw http.ResponseWriter, req *http.Request) {
if key == "" || value == "" {
return
}
ID := t.SAMTunnel.ID()
if id != "" {
ID = t.SAMTunnel.ID() + "." + id
}
fmt.Fprintf(rw, "%s=%s\n", ID, t.SAMTunnel.ID())
}
func PropSort(props map[string]string) []string {
var slice []string
for k, v := range props {
slice = append(slice, k+"="+v)
}
sort.Strings(slice)
return slice
}
func (t *TunnelHandler) ControlForm(rw http.ResponseWriter, req *http.Request) {
if err := req.ParseForm(); err == nil {
if action := req.PostFormValue("action"); action != "" {
var err error
switch action {
case "start":
if !t.SAMTunnel.Up() {
fmt.Println("Starting tunnel", t.ID())
if t.SAMTunnel, err = t.Load(); err == nil {
t.Serve()
}
//return
} else {
fmt.Println(t.ID(), "already started")
req.URL.Path = req.URL.Path + "/color"
}
case "stop":
if t.SAMTunnel.Up() {
fmt.Println("Stopping tunnel", t.ID())
t.Close()
} else {
fmt.Println(t.ID(), "already stopped")
req.URL.Path = req.URL.Path + "/color"
}
case "restart":
if t.SAMTunnel.Up() {
fmt.Println("Stopping tunnel", t.ID())
t.Close()
fmt.Println("Starting tunnel", t.ID())
if t.SAMTunnel, err = t.Load(); err == nil {
t.Serve()
}
return
} else {
fmt.Println(t.ID(), "stopped.")
req.URL.Path = req.URL.Path + "/color"
}
default:
}
}
}
}
func (t *TunnelHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
t.ControlForm(rw, req)
if strings.HasSuffix(req.URL.Path, "color") {
fmt.Fprintf(rw, t.ColorDiv(t.SAMTunnel.ID(), t.SAMTunnel.GetType()))
t.Printdivf(t.SAMTunnel.ID(), "TunName", t.SAMTunnel.ID(), rw, req)
fmt.Fprintf(rw, t.ColorSpan(t.SAMTunnel.ID()))
for _, value := range PropSort(t.SAMTunnel.Props()) {
key := strings.SplitN(value, "=", 2)[0]
val := strings.SplitN(value, "=", 2)[1]
if key != "TunName" {
t.Printdivf(key, key, val, rw, req)
}
}
fmt.Fprintf(rw, t.ColorForm(t.SAMTunnel.ID(), t.SAMTunnel.GetType()))
} else {
t.Printf(t.SAMTunnel.ID(), "TunName", t.SAMTunnel.ID(), rw, req)
for _, value := range PropSort(t.SAMTunnel.Props()) {
key := strings.SplitN(value, "=", 2)[0]
val := strings.SplitN(value, "=", 2)[1]
if key != "TunName" {
t.Printf(key, key, val, rw, req)
}
}
}
}
func NewTunnelHandler(ob samtunnel.SAMTunnel, err error) (*TunnelHandler, error) {
var t TunnelHandler
t.SAMTunnel = ob
return &t, err
}

9903
hashhash/default.go Normal file

File diff suppressed because it is too large Load Diff

76
hashhash/hashhash.go Normal file
View File

@@ -0,0 +1,76 @@
package hashhash
import (
"io/ioutil"
"strings"
)
import (
"github.com/boreq/friendlyhash"
)
type Hasher struct {
FileName string
split []string
length int
hasher *friendlyhash.FriendlyHash
}
func (h *Hasher) dictionary() []string {
if len(h.split) > 0 {
return h.split
}
bytes, _ := ioutil.ReadFile(h.FileName)
h.split = strings.Split(string(bytes), "\n")
return h.split
}
func (h *Hasher) Friendly(input string) (string, error) {
slice, err := h.hasher.Humanize([]byte(input))
if err != nil {
return "", err
}
return strings.Join(slice, " "), nil
}
func (h *Hasher) Unfriendly(input string) (string, error) {
slice := strings.Split(input, " ")
hash, err := h.hasher.Dehumanize(slice)
if err != nil {
return "", err
}
return string(hash), nil
}
func (h *Hasher) Unfriendlyslice(input []string) (string, error) {
hash, err := h.hasher.Dehumanize(input)
if err != nil {
return "", err
}
return string(hash), nil
}
func NewHasher(length int) (*Hasher, error) {
var h Hasher
var err error
h.FileName = ""
h.length = length
h.split = Default()
h.hasher, err = friendlyhash.New(h.dictionary(), length)
if err != nil {
return nil, err
}
return &h, nil
}
func Init(FileName string, length int) (*Hasher, error) {
var h Hasher
var err error
h.FileName = FileName
h.length = length
h.hasher, err = friendlyhash.New(h.dictionary(), length)
if err != nil {
return nil, err
}
return &h, nil
}

94
i2pkeys/common.go Normal file
View File

@@ -0,0 +1,94 @@
package sfi2pkeys
import (
"log"
"os"
"path/filepath"
"strings"
"github.com/eyedeekay/sam-forwarder/i2pkeys/keys"
//"github.com/eyedeekay/sam-forwarder/i2pkeys/password"
"github.com/eyedeekay/sam3"
"github.com/eyedeekay/sam3/i2pkeys"
)
func Encrypt(i2pkeypath, aeskeypath string) error {
return i2pkeyscrypt.EncryptKey(i2pkeypath, aeskeypath)
}
func Decrypt(i2pkeypath, aeskeypath string) error {
return i2pkeyscrypt.DecryptKey(i2pkeypath, aeskeypath)
}
func Save(FilePath, TunName, passfile string, SamKeys i2pkeys.I2PKeys) error {
if _, err := os.Stat(filepath.Join(FilePath, TunName+".i2pkeys")); os.IsNotExist(err) {
file, err := os.Create(filepath.Join(FilePath, TunName+".i2pkeys"))
if err != nil {
return err
}
err = i2pkeys.StoreKeysIncompat(SamKeys, file)
if err != nil {
return err
}
//err = Encrypt(filepath.Join(FilePath, TunName+".i2pkeys"), passfile)
//if err != nil {
//return err
//}
return nil
}
file, err := os.Open(filepath.Join(FilePath, TunName+".i2pkeys"))
if err != nil {
return err
}
//err = Decrypt(filepath.Join(FilePath, TunName+".i2pkeys"), passfile)
//if err != nil {
//return err
//}
SamKeys, err = i2pkeys.LoadKeysIncompat(file)
if err != nil {
return err
}
//SamKeys = &tempkeys
//err = Encrypt(filepath.Join(FilePath, TunName+".i2pkeys"), passfile)
//if err != nil {
//return err
//}
return nil
}
func Load(FilePath, TunName, passfile string, samConn *sam3.SAM, save bool) (i2pkeys.I2PKeys, error) {
if !save {
return samConn.NewKeys()
}
if _, err := os.Stat(filepath.Join(FilePath, TunName+".i2pkeys")); os.IsNotExist(err) {
log.Println("Generating keys from SAM bridge")
SamKeys, err := samConn.NewKeys()
if err != nil {
return i2pkeys.I2PKeys{}, err
}
return SamKeys, nil
}
log.Println("Generating keys from disk")
file, err := os.Open(filepath.Join(FilePath, TunName+".i2pkeys"))
if err != nil {
return i2pkeys.I2PKeys{}, err
}
//err = Decrypt(filepath.Join(FilePath, TunName+".i2pkeys"), passfile)
//if err != nil {
//return i2pkeys.I2PKeys{}, err
//}
return i2pkeys.LoadKeysIncompat(file)
}
func Prop(in string) (string, string) {
k := ""
v := ""
vals := strings.SplitN(in, "=", 2)
if len(vals) >= 1 {
k = vals[0]
}
if len(vals) >= 2 {
v = vals[1]
}
return k, v
}

45
i2pkeys/common_test.go Normal file
View File

@@ -0,0 +1,45 @@
package sfi2pkeys
import (
//"os"
"log"
"testing"
//"path/filepath"
"github.com/eyedeekay/sam3"
)
func TestKeysGenLoad(t *testing.T) {
sc, err := sam3.NewSAM("127.0.0.1:7656")
if err != nil {
t.Fatal(err)
}
log.Println("Initialized SAM connection")
sk, err := Load("./", "test", "", sc, true)
if err != nil {
t.Fatal(err)
}
log.Println("Loaded tunnel keys")
err = Save("./", "test", "", sk)
if err != nil {
t.Fatal(err)
}
}
func TestKeysGenLoadAgain(t *testing.T) {
sc, err := sam3.NewSAM("127.0.0.1:7656")
if err != nil {
t.Fatal(err)
}
log.Println("Saved tunnel keys")
sk, err := Load("./", "test", "", sc, true)
if err != nil {
t.Fatal(err)
}
log.Println("Loaded tunnel keys 2")
err = Save("./", "test2", "", sk)
if err != nil {
t.Fatal(err)
}
log.Println("Saved tunnel keys 2")
}

72
i2pkeys/keys/keys.go Normal file
View File

@@ -0,0 +1,72 @@
package i2pkeyscrypt
import (
"io/ioutil"
"os"
"github.com/gtank/cryptopasta"
)
func bytes(k [32]byte) []byte {
var r []byte
for _, v := range k {
r = append(r, v)
}
return r
}
func key(k []byte) *[32]byte {
var r [32]byte
for i, v := range k {
r[i] = v
}
return &r
}
func EncryptKey(i2pkeypath, aeskeypath string) error {
if aeskeypath != "" {
if r, e := ioutil.ReadFile(i2pkeypath); e != nil {
return e
} else {
if _, err := os.Stat(aeskeypath); os.IsNotExist(err) {
key := cryptopasta.NewEncryptionKey()
ioutil.WriteFile(aeskeypath, bytes(*key), 644)
} else if err != nil {
return err
}
if ra, re := ioutil.ReadFile(aeskeypath); re != nil {
return e
} else {
crypted, err := cryptopasta.Encrypt(r, key(ra))
if err != nil {
return err
}
ioutil.WriteFile(i2pkeypath, crypted, 644)
}
}
}
return nil
}
func DecryptKey(i2pkeypath, aeskeypath string) error {
if aeskeypath != "" {
if r, e := ioutil.ReadFile(i2pkeypath); e != nil {
return e
} else {
if _, err := os.Stat(aeskeypath); os.IsNotExist(err) {
return err
}
if ra, re := ioutil.ReadFile(aeskeypath); re != nil {
return e
} else {
crypted, err := cryptopasta.Decrypt(r, key(ra))
if err != nil {
return err
}
ioutil.WriteFile(i2pkeypath, crypted, 644)
}
//crypted
}
}
return nil
}

View File

@@ -0,0 +1,35 @@
package i2pkeyspass
import (
//"io/ioutil"
//"os"
//"log"
//"path/filepath"
//"github.com/eyedeekay/sam3"
//"github.com/gtank/cryptopasta"
)
func bytes(k [32]byte) []byte {
var r []byte
for _, v := range k {
r = append(r, v)
}
return r
}
func key(k []byte) *[32]byte {
var r [32]byte
for i, v := range k {
r[i] = v
}
return &r
}
func EncryptPassword(i2pkeypath, password string) error {
return nil
}
func DecryptPassword(i2pkeypath, password string) error {
return nil
}

26
interface/README.md Normal file
View File

@@ -0,0 +1,26 @@
Implementing the sam-forwarder interface
========================================
The sam-forwrder interface(used int the Go sense of the word interface) is used
to create custom types of tunnels. It's kind of big, and maybe too complex, so
subject to change.
``` go
type SAMTunnel interface {
GetType() string
Cleanup()
Print() string
Props() map[string]string
Search(search string) string
Target() string
ID() string
//Destination() string
Base32() string
Base64() string
Keys() i2pkeys.I2PKeys
Serve() error
Close() error
Up() bool
Load() (SAMTunnel, error)
}
```

60
interface/interface.go Normal file
View File

@@ -0,0 +1,60 @@
package samtunnel
import (
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam3/i2pkeys"
)
// SAMTunnel is an interface comprehensively representing an I2P tunnel over SAM
// in Go
type SAMTunnel interface {
// Config returns the appropriate underlying config object all options, or
// the common options passed into a compound tunnel.
Config() *i2ptunconf.Conf
// Tunnel Options
// GetType Get the type of the tunnel in use(server, client, http, udp, etc)
GetType() string
// Print all the tunnel options as a string
Print() string
// Props Get a full list of tunnel properties as a map for user display/analysis
Props() map[string]string
//Search the Props for a common term
Search(search string) string
//Target The address of the local client or service to forward with a SAM tunnel
Target() string
//ID The user-chosen tunnel name
ID() string
//Destination() string
// Key handling
// Get the .b32.i2p address of your service
Base32() string
// Create a more-readable representation of the .b32.i2p address using English words
Base32Readable() string
// Get the public base64 address of your I2P service
Base64() string
// Get all the parts of the keys to your I2P service
Keys() i2pkeys.I2PKeys
// Service Management
// Prepare tunnel keys and tunnel options
Load() (SAMTunnel, error)
// Start the tunnel
Serve() error
// Stop the tunnel and close all connections
Close() error
// Stop the tunnel but leave the sockets alone for now
Cleanup()
// Return "true" if the tunnel is ready to go up.
Up() bool
}
// WebUI is an interface which is used to generate a minimal UI. Open to suggestions.
type WebUI interface {
Title() string
URL() string
UseWebUI() bool
Width() int
Height() int
Resizable() bool
}

View File

@@ -1,17 +0,0 @@
package encryptedleasesetkeys
//import (
//"crypto/x509"
//)
type LeaseSetKey struct {
//LeaseSetPrivateKey
//LeaseSetPrivateSigningKey
//
}
/*
// Get
func Get() error {
}
*/

View File

@@ -1,25 +0,0 @@
package main
import "log"
import "github.com/eyedeekay/sam-forwarder/config"
func clientMode() {
if *udpMode {
log.Println("Proxying udp", *targetHost+":"+*targetPort, "to", *targetDestination)
forwarder, err := i2ptunconf.NewSAMSSUClientForwarderFromConf(config)
if err == nil {
forwarder.Serve(*targetDestination)
} else {
log.Println(err.Error())
}
} else {
log.Println("Proxying tcp", *targetHost+":"+*targetPort, "to", *targetDestination)
forwarder, err := i2ptunconf.NewSAMClientForwarderFromConf(config)
if err == nil {
forwarder.Serve(*targetDestination)
} else {
log.Println(err.Error())
}
}
}

View File

@@ -1,119 +0,0 @@
package main
import (
"flag"
"log"
"strings"
)
import "github.com/eyedeekay/sam-forwarder/config"
type flagOpts []string
func (f *flagOpts) String() string {
r := ""
for _, s := range *f {
r += s + ","
}
return strings.TrimSuffix(r, ",")
}
func (f *flagOpts) Set(s string) error {
*f = append(*f, s)
return nil
}
func (f *flagOpts) StringSlice() []string {
var r []string
for _, s := range *f {
r = append(r, s)
}
return r
}
var (
saveFile = flag.Bool("save", false, "Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.")
encryptLeaseSet = flag.Bool("encryptlease", true, "Use an encrypted leaseset(true or false)")
inAllowZeroHop = flag.Bool("zeroin", false, "Allow zero-hop, non-anonymous tunnels in(true or false)")
outAllowZeroHop = flag.Bool("zeroout", false, "Allow zero-hop, non-anonymous tunnels out(true or false)")
useCompression = flag.Bool("gzip", false, "Uze gzip(true or false)")
reduceIdle = flag.Bool("reduce", false, "Reduce tunnel quantity when idle(true or false)")
closeIdle = flag.Bool("close", false, "Close tunnel idle(true or false)")
udpMode = flag.Bool("udp", false, "UDP mode(true or false)")
client = flag.Bool("client", false, "Client proxy mode(true or false)")
injectHeaders = flag.Bool("headers", false, "Inject X-I2P-DEST headers")
encryptedLeasesetKeys = flag.String("lsk", "none", "path to saved encrypted leaseset keys")
targetDir = flag.String("dir", "", "Directory to save tunnel configuration file in.")
iniFile = flag.String("ini", "none", "Use an ini file for configuration(config file options override passed arguments for now.)")
targetDestination = flag.String("dest", "none", "Destination for client tunnels. Ignored for service tunnels.")
targetHost = flag.String("host", "127.0.0.1", "Target host(Host of service to forward to i2p)")
targetPort = flag.String("port", "8081", "Target port(Port of service to forward to i2p)")
targetPort443 = flag.String("tlsport", "", "(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)")
samHost = flag.String("samhost", "127.0.0.1", "SAM host")
samPort = flag.String("samport", "7656", "SAM port")
tunName = flag.String("name", "forwarder", "Tunnel name, this must be unique but can be anything.")
accessListType = flag.String("access", "none", "Type of access list to use, can be \"whitelist\" \"blacklist\" or \"none\".")
inLength = flag.Int("inlen", 3, "Set inbound tunnel length(0 to 7)")
outLength = flag.Int("outlen", 3, "Set outbound tunnel length(0 to 7)")
inQuantity = flag.Int("incount", 6, "Set inbound tunnel quantity(0 to 15)")
outQuantity = flag.Int("outcount", 6, "Set outbound tunnel quantity(0 to 15)")
inVariance = flag.Int("invar", 0, "Set inbound tunnel length variance(-7 to 7)")
outVariance = flag.Int("outvar", 0, "Set outbound tunnel length variance(-7 to 7)")
inBackupQuantity = flag.Int("inback", 4, "Set inbound tunnel backup quantity(0 to 5)")
outBackupQuantity = flag.Int("outback", 4, "Set outbound tunnel backup quantity(0 to 5)")
reduceIdleTime = flag.Int("reducetime", 600000, "Reduce tunnel quantity after X (milliseconds)")
closeIdleTime = flag.Int("closetime", 600000, "Reduce tunnel quantity after X (milliseconds)")
reduceIdleQuantity = flag.Int("reducecount", 3, "Reduce idle tunnel quantity to X (0 to 5)")
)
var err error
var accessList flagOpts
var config *i2ptunconf.Conf
func main() {
flag.Var(&accessList, "accesslist", "Specify an access list member(can be used multiple times)")
flag.Parse()
config = i2ptunconf.NewI2PBlankTunConf()
if *iniFile != "none" {
config, err = i2ptunconf.NewI2PTunConf(*iniFile)
}
config.TargetHost = config.GetHost(*targetHost, "127.0.0.1")
config.TargetPort = config.GetPort(*targetPort, "8081")
config.SaveFile = config.GetSaveFile(*saveFile, true)
config.SaveDirectory = config.GetDir(*targetDir, "../")
config.SamHost = config.GetSAMHost(*samHost, "127.0.0.1")
config.SamPort = config.GetSAMPort(*samPort, "7656")
config.TunName = config.GetKeys(*tunName, "forwarder")
config.InLength = config.GetInLength(*inLength, 3)
config.OutLength = config.GetOutLength(*outLength, 3)
config.InVariance = config.GetInVariance(*inVariance, 0)
config.OutVariance = config.GetOutVariance(*outVariance, 0)
config.InQuantity = config.GetInQuantity(*inQuantity, 6)
config.OutQuantity = config.GetOutQuantity(*outQuantity, 6)
config.InBackupQuantity = config.GetInBackups(*inBackupQuantity, 5)
config.OutBackupQuantity = config.GetOutBackups(*outBackupQuantity, 5)
config.EncryptLeaseSet = config.GetEncryptLeaseset(*encryptLeaseSet, false)
config.InAllowZeroHop = config.GetInAllowZeroHop(*inAllowZeroHop, false)
config.OutAllowZeroHop = config.GetOutAllowZeroHop(*outAllowZeroHop, false)
config.UseCompression = config.GetUseCompression(*useCompression, true)
config.ReduceIdle = config.GetReduceOnIdle(*reduceIdle, true)
config.ReduceIdleTime = config.GetReduceIdleTime(*reduceIdleTime, 600000)
config.ReduceIdleQuantity = config.GetReduceIdleQuantity(*reduceIdleQuantity, 2)
config.AccessListType = config.GetAccessListType(*accessListType, "none")
config.CloseIdle = config.GetCloseOnIdle(*closeIdle, false)
config.CloseIdleTime = config.GetCloseIdleTime(*closeIdleTime, 600000)
config.Type = config.GetType(*client, *udpMode, *injectHeaders, "server")
config.TargetForPort443 = config.GetPort443(*targetPort443, "")
if config.Client {
if *targetDestination == "none" {
log.Fatal("Client mode requires you to specify a base32 or jump destination")
} else {
log.Println("Client mode is still experimental.")
clientMode()
}
} else {
serveMode()
}
}

View File

@@ -1,25 +0,0 @@
package main
import "log"
import "github.com/eyedeekay/sam-forwarder/config"
func serveMode() {
if *udpMode {
log.Println("Redirecting udp", *targetHost+":"+*targetPort, "to i2p")
forwarder, err := i2ptunconf.NewSAMSSUForwarderFromConf(config)
if err == nil {
forwarder.Serve()
} else {
log.Println(err.Error())
}
} else {
log.Println("Redirecting tcp", *targetHost+":"+*targetPort, "to i2p")
forwarder, err := i2ptunconf.NewSAMForwarderFromConf(config)
if err == nil {
forwarder.Serve()
} else {
log.Println(err.Error())
}
}
}

28
manager/manager-conn.go Normal file
View File

@@ -0,0 +1,28 @@
package sammanager
import (
"context"
"net"
"os"
"time"
)
func (s *SAMManager) Dial(network, address string) (net.Conn, error) {
return nil, nil
}
func (s *SAMManager) DialContext(ctx context.Context, network, address string) (*net.Conn, error) {
return nil, nil
}
func (s *SAMManager) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
return nil, nil
}
func (s *SAMManager) FileConn(f *os.File) (c net.Conn, err error) {
return nil, nil
}
func (s *SAMManager) Pipe() (net.Conn, net.Conn) {
return nil, nil
}

136
manager/manager-options.go Normal file
View File

@@ -0,0 +1,136 @@
package sammanager
import (
"fmt"
"strconv"
)
import "github.com/eyedeekay/sam-forwarder/config"
//ManagerOption is a SAMManager Option
type ManagerOption func(*SAMManager) error
//SetManagerFilePath sets the host of the SAMManager's SAM bridge
func SetManagerFilePath(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.config.FilePath = s
return nil
}
}
//SetManagerHost sets the host of the SAMManager's SAM bridge
func SetManagerHost(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.ServerHost = s
return nil
}
}
//SetManagerWebUser sets the host of the SAMManager's SAM bridge
func SetManagerWebUser(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.config.UserName = s
return nil
}
}
//SetManagerWebPass sets the host of the SAMManager's SAM bridge
func SetManagerWebPass(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.config.Password = s
return nil
}
}
//SetManagerPort sets the port of the SAMManager's SAM bridge using a string
func SetManagerPort(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Manager Server Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.ServerPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetManagerSAMHost sets the host of the SAMManager's SAM bridge
func SetManagerSAMHost(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.SamHost = s
return nil
}
}
//SetManagerSAMPort sets the port of the SAMManager's SAM bridge using a string
func SetManagerSAMPort(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Manager SAM Port %s; non-number", s)
}
if port < 65536 && port > -1 {
c.SamPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetManagerWebHost sets the host of the SAMManager's SAM bridge
func SetManagerWebHost(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.WebHost = s
return nil
}
}
//SetManagerWebPort sets the port of the SAMManager's SAM bridge using a string
func SetManagerWebPort(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Manager SAM Port %s; non-number", s)
}
if port < 65536 && port > -1 {
c.WebPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetManagerConf sets the host of the SAMManager's SAM bridge
func SetManagerConf(s *i2ptunconf.Conf) func(*SAMManager) error {
return func(c *SAMManager) error {
c.config = s
return nil
}
}
//SetManagerStart sets the host of the SAMManager's SAM bridge
func SetManagerStart(s bool) func(*SAMManager) error {
return func(c *SAMManager) error {
c.start = s
return nil
}
}
//SetManagerWeb sets the host of the SAMManager's SAM bridge
func SetManagerWeb(s bool) func(*SAMManager) error {
return func(c *SAMManager) error {
c.UseWeb = s
return nil
}
}
//SetTunName sets the host of the SAMManager's SAM bridge
func SetTunName(s string) func(*SAMManager) error {
return func(c *SAMManager) error {
c.tunName = s
return nil
}
}

361
manager/manager.go Normal file
View File

@@ -0,0 +1,361 @@
package sammanager
import (
//"fmt"
"log"
"os/exec"
"os/user"
"runtime"
"strconv"
)
import (
"github.com/eyedeekay/portcheck"
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/config/helpers"
"github.com/eyedeekay/sam-forwarder/handler"
"github.com/justinas/nosurf"
)
type SAMManager struct {
start bool
config *i2ptunconf.Conf
tunName string
ServerHost string
ServerPort string
SamHost string
SamPort string
UseWeb bool
WebHost string
WebPort string
cssFile string
jsFile string
handlerMux *samtunnelhandler.TunnelHandlerMux
}
var err error
func (s *SAMManager) Cleanup() {
for _, k := range s.handlerMux.Tunnels() {
k.Cleanup()
}
}
func (s *SAMManager) UseWebUI() bool {
return s.UseWeb
}
func (s *SAMManager) Title() string {
return s.config.UserName
}
func (s *SAMManager) Width() int {
return 800
}
func (s *SAMManager) Height() int {
return 600
}
func (s *SAMManager) Resizable() bool {
return true
}
func (s *SAMManager) URL() string {
return "http://" + s.WebHost + ":" + s.WebPort
}
func User() string {
runningUser, _ := user.Current()
if runtime.GOOS != "windows" {
if runningUser.Uid == "0" {
cmd := exec.Command("logname")
out, err := cmd.Output()
if err != nil {
return err.Error()
}
return string(out)
}
}
return runningUser.Name
}
var runningUser = User()
func NewSAMManagerFromOptions(opts ...func(*SAMManager) error) (*SAMManager, error) {
var s SAMManager
s.config = i2ptunconf.NewI2PBlankTunConf()
s.config.FilePath = ""
s.start = false
s.UseWeb = true
s.ServerHost = "localhost"
s.ServerPort = "8081"
s.SamHost = "localhost"
s.SamPort = "7656"
s.WebHost = "localhost"
s.WebPort = "7957"
s.tunName = "samcatd-"
s.config.UserName = "samcatd"
s.config.Password = ""
s.cssFile = ""
s.jsFile = ""
for _, o := range opts {
if err := o(&s); err != nil {
return nil, err
}
}
log.Println("MANAGER INITIALIZING")
if port, err := strconv.Atoi(s.WebPort); err != nil {
log.Println("Error:", err)
return nil, err
} else {
if pc.SCL(port) {
log.Println("Service found, launching GUI")
s.RunUI()
return nil, nil
}
}
s.handlerMux = samtunnelhandler.NewTunnelHandlerMux(s.WebHost, s.WebPort, s.config.UserName, s.config.Password, s.cssFile, s.jsFile)
log.Println("tunnel settings from", s.config.FilePath, "are", s.ServerHost, s.ServerPort, s.SamHost, s.SamPort)
var err error
if s.config.FilePath != "" {
s.config, err = i2ptunconf.NewI2PTunConf(s.config.FilePath)
s.config.TargetHost = s.config.GetHost(s.ServerHost, "127.0.0.1")
s.config.TargetPort = s.config.GetPort(s.ServerPort, "8081")
if err != nil {
return nil, err
}
log.Println("Manager found Labels", s.config.Labels)
for _, label := range s.config.Labels {
log.Println("Processing tunnel for label", label)
if t, e := s.config.Get("type", label); e {
switch t {
case "http":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found http under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "httpclient":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMHTTPClientFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found http under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "server":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found server under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "client":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMClientForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found client under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "udpserver":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found udpserver under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "udpclient":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGClientForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found udpclient under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "eephttpd":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewEepHttpdFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found eephttpd under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "outproxy":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewOutProxyFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found outproxy under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "outproxyhttp":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewHttpOutProxyFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found outproxy under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
/*case "vpnserver":
if f, e := samtunnelhandler.NewTunnelHandler(samforwardervpnserver.NewSAMVPNForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found vpnserver under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "vpnclient":
if f, e := samtunnelhandler.NewTunnelHandler(samforwardervpn.NewSAMVPNClientForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found vpnclient under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}*/
default:
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConfig(s.config.FilePath, s.SamHost, s.SamPort, label)); e == nil {
log.Println("found server under", label)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
}
}
}
} else {
t, b := s.config.Get("type")
if !b {
t = "httpclient"
//return nil, fmt.Errorf("samcat was instructed to start a tunnel with insufficient default settings information.")
}
switch t {
case "http":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConf(s.config)); e == nil {
log.Println("found default http")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "httpclient":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMHTTPClientFromConf(s.config)); e == nil {
log.Println("found default httpclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "browserclient":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMBrowserClientFromConf(s.config)); e == nil {
log.Println("found default browserclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "server":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConf(s.config)); e == nil {
log.Println("found default server")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "client":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMClientForwarderFromConf(s.config)); e == nil {
log.Println("found default client")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "udpserver":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGForwarderFromConf(s.config)); e == nil {
log.Println("found default udpserver")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "udpclient":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGClientForwarderFromConf(s.config)); e == nil {
log.Println("found default udpclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "eephttpd":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewEepHttpdFromConf(s.config)); e == nil {
log.Println("found default udpclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "outproxy":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewOutProxyFromConf(s.config)); e == nil {
log.Println("found default udpclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "outproxyhttp":
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewHttpOutProxyFromConf(s.config)); e == nil {
log.Println("found default udpclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
/*case "vpnserver":
if f, e := samtunnelhandler.NewTunnelHandler(samforwardervpnserver.NewSAMVPNForwarderFromConf(s.config)); e == nil {
log.Println("found default vpnserver")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
case "vpnclient":
if f, e := samtunnelhandler.NewTunnelHandler(samforwardervpn.NewSAMVPNClientForwarderFromConf(s.config)); e == nil {
log.Println("found default vpnclient")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}*/
default:
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMClientForwarderFromConf(s.config)); e == nil {
log.Println("found default client")
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, e
}
}
}
s.handlerMux.Handler = nosurf.New(s.handlerMux.Handler)
return &s, nil
}
func NewSAMManager(inifile, servhost, servport, samhost, samport, webhost, webport, cssfile, jsfile string, start, web bool, webuser, webpass string) (*SAMManager, error) {
log.Println("tunnel settings", servhost, servport, samhost, samport)
return NewSAMManagerFromOptions(
SetManagerFilePath(inifile),
SetManagerHost(servhost),
SetManagerPort(servport),
SetManagerSAMHost(samhost),
SetManagerSAMPort(samport),
SetManagerWebHost(webhost),
SetManagerWebPort(webport),
SetManagerStart(start),
SetManagerWebUser(webuser),
SetManagerWebPass(webpass),
SetManagerWeb(web),
)
}
func NewSAMManagerFromConf(conf *i2ptunconf.Conf, servhost, servport, samhost, samport, webhost, webport, cssfile, jsfile string, start, web bool, webuser, webpass string) (*SAMManager, error) {
log.Println("tunnel settings", servhost, servport, samhost, samport)
return NewSAMManagerFromOptions(
SetManagerConf(conf),
SetManagerHost(servhost),
SetManagerPort(servport),
SetManagerSAMHost(samhost),
SetManagerSAMPort(samport),
SetManagerWebHost(webhost),
SetManagerWebPort(webport),
SetManagerStart(start),
SetManagerWebUser(webuser),
SetManagerWebPass(webpass),
SetManagerWeb(web),
)
}

186
manager/manager_test.go Normal file
View File

@@ -0,0 +1,186 @@
package sammanager
import (
"fmt"
"log"
"strings"
"testing"
)
func stringify(s []string) string {
var p string
for _, x := range s {
if x != "ntcpserver" && x != "httpserver" && x != "ssuserver" && x != "ntcpclient" && x != "ssuclient" {
p += x + ","
}
}
r := strings.Trim(strings.Trim(strings.Replace(p, ",,", ",", -1), " "), "\n")
return r
}
func (s *SAMManager) List(search ...string) *[]string {
var r []string
if search == nil {
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Print()))
}
return &r
} else if len(search) > 0 {
switch search[0] {
case "":
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Print()))
}
return &r
case "ntcpserver":
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "httpserver":
for index, element := range s.handlerMux.Tunnels() {
if element.GetType() == "http" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
return &r
case "ntcpclient":
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "ssuserver":
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "ssuclient":
for index, element := range s.handlerMux.Tunnels() {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
default:
for index, element := range s.handlerMux.Tunnels() {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.handlerMux.Tunnels() {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.handlerMux.Tunnels() {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.handlerMux.Tunnels() {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
return &r
}
}
return &r
}
func TestOption0(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8080"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7958"),
SetManagerFilePath("../etc/sam-forwarder/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List())
}
func TestOption1(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8081"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7959"),
SetManagerFilePath("../etc/sam-forwarder/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List(""))
}
func TestOption2(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8082"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7960"),
SetManagerFilePath("../etc/sam-forwarder/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List("asdgrepgbutwhrsgfbxv"))
}
func TestOption3(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8083"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7961"),
SetManagerFilePath("none"),
SetManagerFilePath("../etc/sam-forwarder/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List("server"))
}
func TestOption4(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8083"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7961"),
SetManagerFilePath("none"),
SetManagerFilePath("../etc/sam-forwarder/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List(""))
}
func TestOption5(t *testing.T) {
client, err := NewSAMManagerFromOptions(
SetManagerHost("127.0.0.1"),
SetManagerSAMHost("127.0.0.1"),
SetManagerPort("8083"),
SetManagerSAMPort("7656"),
SetManagerWebHost("127.0.0.1"),
SetManagerWebPort("7961"),
SetManagerFilePath("none"),
SetManagerFilePath("../etc/samcatd/tunnels.ini"),
)
if err != nil {
t.Fatalf("NewSAMManager() Error: %q\n", err)
}
log.Println(client.List(""))
}

68
manager/nostatic.go Normal file
View File

@@ -0,0 +1,68 @@
// +build nostatic
// +build !static !cli
package sammanager
import (
"log"
"os"
"os/signal"
"time"
)
import (
. "github.com/eyedeekay/sam-forwarder/gui"
"github.com/zserge/webview"
)
var view webview.WebView
func (s *SAMManager) RunUI() {
view, err = LaunchUI(s)
if err != nil {
log.Println(err.Error())
}
//go
view.Run()
}
func (s *SAMManager) Serve() bool {
log.Println("Starting Tunnels()")
for _, element := range s.handlerMux.Tunnels() {
log.Println("Starting service tunnel", element.ID())
go element.Serve()
}
if s.UseWebUI() == true {
go s.handlerMux.ListenAndServe()
if view, err = LaunchUI(s); err != nil {
log.Println("UI Error:", err.Error())
return false
} else {
view.Run()
return true
}
} else {
return Exit()
}
return false
}
func Exit() bool {
Close := false
for !Close {
time.Sleep(1 * time.Second)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
log.Println(sig)
if view != nil {
view.Exit()
}
Close = true
}
}()
}
return Close
}

41
manager/noui.go Normal file
View File

@@ -0,0 +1,41 @@
// +build cli
// +build !nostatic !static
package sammanager
import (
"log"
"os"
"os/signal"
"time"
)
func (s *SAMManager) RunUI() {
}
func (s *SAMManager) Serve() bool {
log.Println("Starting Tunnels()")
for _, element := range s.handlerMux.Tunnels() {
log.Println("Starting service tunnel", element.ID())
go element.Serve()
}
return Exit()
}
func Exit() bool {
Close := false
for !Close {
time.Sleep(1 * time.Second)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
log.Println(sig)
Close = true
}
}()
}
return false
}

65
manager/static.go Normal file
View File

@@ -0,0 +1,65 @@
// +build static
// +build !nostatic !cli
package sammanager
import (
"log"
"os"
"os/signal"
"time"
)
import (
. "github.com/eyedeekay/sam-forwarder/gui"
"github.com/zserge/lorca"
)
var view lorca.UI
func (s *SAMManager) RunUI() {
view, err = LaunchUI(s)
if err != nil {
log.Println(err.Error())
}
}
func (s *SAMManager) Serve() bool {
log.Println("Starting Tunnels()")
for _, element := range s.handlerMux.Tunnels() {
log.Println("Starting service tunnel", element.ID())
go element.Serve()
}
if s.UseWebUI() == true {
go s.handlerMux.ListenAndServe()
if view, err = LaunchUI(s); err != nil {
log.Println(err.Error())
return Exit()
} else {
return Exit()
}
} else {
return Exit()
}
return false
}
func Exit() bool {
Close := false
for !Close {
time.Sleep(1 * time.Second)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
log.Println(sig)
if view != nil {
view.Close()
}
Close = true
}
}()
}
return Close
}

450
options/options.go Normal file
View File

@@ -0,0 +1,450 @@
package samoptions
import (
"fmt"
"strconv"
"github.com/eyedeekay/sam-forwarder/interface"
)
//Option is a SAMForwarder Option
type Option func(samtunnel.SAMTunnel) error
//SetFilePath sets the path to save the config file at.
func SetFilePath(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().FilePath = s
return nil
}
}
//SetType sets the type of the forwarder server
func SetType(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if s == "http" {
c.Config().Type = s
return nil
} else {
c.Config().Type = "server"
return nil
}
}
}
//SetSigType sets the type of the forwarder server
func SetSigType(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if s == "" {
c.Config().SigType = ""
} else if s == "DSA_SHA1" {
c.Config().SigType = "DSA_SHA1"
} else if s == "ECDSA_SHA256_P256" {
c.Config().SigType = "ECDSA_SHA256_P256"
} else if s == "ECDSA_SHA384_P384" {
c.Config().SigType = "ECDSA_SHA384_P384"
} else if s == "ECDSA_SHA512_P521" {
c.Config().SigType = "ECDSA_SHA512_P521"
} else if s == "EdDSA_SHA512_Ed25519" {
c.Config().SigType = "EdDSA_SHA512_Ed25519"
} else {
c.Config().SigType = "EdDSA_SHA512_Ed25519"
}
return nil
}
}
//SetSaveFile tells the router to save the tunnel's keys long-term
func SetSaveFile(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().SaveFile = b
return nil
}
}
//SetHost sets the host of the service to forward
func SetHost(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().TargetHost = s
return nil
}
}
//SetPort sets the port of the service to forward
func SetPort(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid TCP Server Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.Config().TargetPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetSAMHost sets the host of the SAMForwarder's SAM bridge
func SetSAMHost(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().SamHost = s
return nil
}
}
//SetSAMPort sets the port of the SAMForwarder's SAM bridge using a string
func SetSAMPort(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid SAM Port %s; non-number", s)
}
if port < 65536 && port > -1 {
c.Config().SamPort = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
//SetName sets the host of the SAMForwarder's SAM bridge
func SetName(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().TunName = s
return nil
}
}
//SetInLength sets the number of hops inbound
func SetInLength(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u < 7 && u >= 0 {
c.Config().InLength = u
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetOutLength sets the number of hops outbound
func SetOutLength(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u < 7 && u >= 0 {
c.Config().OutLength = u
return nil
}
return fmt.Errorf("Invalid outbound tunnel length")
}
}
//SetInVariance sets the variance of a number of hops inbound
func SetInVariance(i int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if i < 7 && i > -7 {
c.Config().InVariance = i
return nil
}
return fmt.Errorf("Invalid inbound tunnel length")
}
}
//SetOutVariance sets the variance of a number of hops outbound
func SetOutVariance(i int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if i < 7 && i > -7 {
c.Config().OutVariance = i
return nil
}
return fmt.Errorf("Invalid outbound tunnel variance")
}
}
//SetInQuantity sets the inbound tunnel quantity
func SetInQuantity(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u <= 16 && u > 0 {
c.Config().InQuantity = u
return nil
}
return fmt.Errorf("Invalid inbound tunnel quantity")
}
}
//SetOutQuantity sets the outbound tunnel quantity
func SetOutQuantity(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u <= 16 && u > 0 {
c.Config().OutQuantity = u
return nil
}
return fmt.Errorf("Invalid outbound tunnel quantity")
}
}
//SetInBackups sets the inbound tunnel backups
func SetInBackups(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u < 6 && u >= 0 {
c.Config().InBackupQuantity = u
return nil
}
return fmt.Errorf("Invalid inbound tunnel backup quantity")
}
}
//SetOutBackups sets the inbound tunnel backups
func SetOutBackups(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u < 6 && u >= 0 {
c.Config().OutBackupQuantity = u
return nil
}
return fmt.Errorf("Invalid outbound tunnel backup quantity")
}
}
//SetEncrypt tells the router to use an encrypted leaseset
func SetEncrypt(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().EncryptLeaseSet = true
return nil
}
c.Config().EncryptLeaseSet = false
return nil
}
}
//SetLeaseSetKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetKey(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().LeaseSetKey = s
return nil
}
}
//SetLeaseSetPrivateKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateKey(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().LeaseSetPrivateKey = s
return nil
}
}
//SetLeaseSetPrivateSigningKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateSigningKey(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().LeaseSetPrivateSigningKey = s
return nil
}
}
//SetMessageReliability sets the host of the SAMForwarder's SAM bridge
func SetMessageReliability(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().MessageReliability = s
return nil
}
}
//SetAllowZeroIn tells the tunnel to accept zero-hop peers
func SetAllowZeroIn(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().InAllowZeroHop = true
return nil
}
c.Config().InAllowZeroHop = false
return nil
}
}
//SetAllowZeroOut tells the tunnel to accept zero-hop peers
func SetAllowZeroOut(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().OutAllowZeroHop = true
return nil
}
c.Config().OutAllowZeroHop = false
return nil
}
}
//SetCompress tells clients to use compression
func SetCompress(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().UseCompression = true
return nil
}
c.Config().UseCompression = false
return nil
}
}
//SetFastRecieve tells clients to use compression
func SetFastRecieve(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().FastRecieve = true
return nil
}
c.Config().FastRecieve = false
return nil
}
}
//SetReduceIdle tells the connection to reduce it's tunnels during extended idle time.
func SetReduceIdle(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().ReduceIdle = true
return nil
}
c.Config().ReduceIdle = false
return nil
}
}
//SetReduceIdleTime sets the time to wait before reducing tunnels to idle levels
func SetReduceIdleTime(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().ReduceIdleTime = 300000
if u >= 6 {
c.Config().ReduceIdleTime = (u * 60) * 1000
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in minutes) %v", u)
}
}
//SetReduceIdleTimeMs sets the time to wait before reducing tunnels to idle levels in milliseconds
func SetReduceIdleTimeMs(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().ReduceIdleTime = 300000
if u >= 300000 {
c.Config().ReduceIdleTime = u
return nil
}
return fmt.Errorf("Invalid reduce idle timeout(Measured in milliseconds) %v", u)
}
}
//SetReduceIdleQuantity sets minimum number of tunnels to reduce to during idle time
func SetReduceIdleQuantity(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if u < 5 {
c.Config().ReduceIdleQuantity = u
return nil
}
return fmt.Errorf("Invalid reduce tunnel quantity")
}
}
//SetCloseIdle tells the connection to close it's tunnels during extended idle time.
func SetCloseIdle(b bool) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if b {
c.Config().CloseIdle = true
return nil
}
c.Config().CloseIdle = false
return nil
}
}
//SetCloseIdleTime sets the time to wait before closing tunnels to idle levels
func SetCloseIdleTime(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().CloseIdleTime = 300000
if u >= 6 {
c.Config().CloseIdleTime = (u * 60) * 1000
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in minutes) %v", u)
}
}
//SetCloseIdleTimeMs sets the time to wait before closing tunnels to idle levels in milliseconds
func SetCloseIdleTimeMs(u int) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().CloseIdleTime = 300000
if u >= 300000 {
c.Config().CloseIdleTime = u
return nil
}
return fmt.Errorf("Invalid close idle timeout(Measured in milliseconds) %v", u)
}
}
//SetAccessListType tells the system to treat the AccessList as a allowlist
func SetAccessListType(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if s == "allowlist" {
c.Config().AccessListType = "allowlist"
return nil
} else if s == "blocklist" {
c.Config().AccessListType = "blocklist"
return nil
} else if s == "none" {
c.Config().AccessListType = ""
return nil
} else if s == "" {
c.Config().AccessListType = ""
return nil
}
return fmt.Errorf("Invalid Access list type(allowlist, blocklist, none)")
}
}
//SetAccessList tells the system to treat the AccessList as a allowlist
func SetAccessList(s []string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
if len(s) > 0 {
for _, a := range s {
c.Config().AccessList = append(c.Config().AccessList, a)
}
return nil
}
return nil
}
}
//SetTargetForPort sets the port of the SAMForwarder's SAM bridge using a string
/*func SetTargetForPort443(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
port, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("Invalid Target Port %s; non-number ", s)
}
if port < 65536 && port > -1 {
c.Config().TargetForPort443 = s
return nil
}
return fmt.Errorf("Invalid port")
}
}
*/
//SetKeyFile sets
func SetKeyFile(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().KeyFilePath = s
return nil
}
}
func SetPassword(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().KeyFilePath = s
return nil
}
}
func SetDestination(s string) func(samtunnel.SAMTunnel) error {
return func(c samtunnel.SAMTunnel) error {
c.Config().ClientDest = s
return nil
}
}

261
samcatd/main.go Normal file
View File

@@ -0,0 +1,261 @@
package main
import (
"context"
"flag"
"log"
"os"
"os/signal"
"strconv"
"strings"
)
import (
"crawshaw.io/littleboss"
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/hashhash"
"github.com/eyedeekay/sam-forwarder/manager"
)
type flagOpts []string
func (f *flagOpts) String() string {
r := ""
for _, s := range *f {
r += s + ","
}
return strings.TrimSuffix(r, ",")
}
func (f *flagOpts) Set(s string) error {
*f = append(*f, s)
return nil
}
func (f *flagOpts) StringSlice() []string {
var r []string
for _, s := range *f {
r = append(r, s)
}
return r
}
var (
saveFile = flag.Bool("t", false,
"Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.")
startUp = flag.Bool("s", false,
"Start a tunnel with the passed parameters(Otherwise, they will be treated as default values.)")
encryptLeaseSet = flag.Bool("l", true,
"Use an encrypted leaseset(true or false)")
encryptKeyFiles = flag.String("cr", "",
"Encrypt/decrypt the key files with a passfile")
inAllowZeroHop = flag.Bool("zi", false,
"Allow zero-hop, non-anonymous tunnels in(true or false)")
outAllowZeroHop = flag.Bool("zo", false,
"Allow zero-hop, non-anonymous tunnels out(true or false)")
useCompression = flag.Bool("z", false,
"Uze gzip(true or false)")
reduceIdle = flag.Bool("r", false,
"Reduce tunnel quantity when idle(true or false)")
closeIdle = flag.Bool("x", false,
"Close tunnel group after idle(true or false)")
udpMode = flag.Bool("u", false,
"UDP mode(true or false)")
client = flag.Bool("c", false,
"Client proxy mode(true or false)")
injectHeaders = flag.Bool("ih", false,
"Inject X-I2P-DEST headers")
webAdmin = flag.Bool("w", true,
"Start web administration interface")
sigType = flag.String("st", "",
"Signature type")
webPort = flag.String("wp", "7957",
"Web port")
webUser = flag.String("webuser", "samcatd",
"Web interface username")
webPass = flag.String("webpass", "",
"Web interface password")
webCSS = flag.String("css", "css/styles.css",
"custom CSS for web interface")
webJS = flag.String("js", "js/scripts.js",
"custom JS for web interface")
webDir = flag.String("wwwdir", "./www",
"Default www directory to serve if starting eephttpd")
leaseSetKey = flag.String("k", "none",
"key for encrypted leaseset")
leaseSetPrivateKey = flag.String("pk", "none",
"private key for encrypted leaseset")
leaseSetPrivateSigningKey = flag.String("psk", "none",
"private signing key for encrypted leaseset")
targetDir = flag.String("d", "",
"Directory to save tunnel configuration file in.")
targetDest = flag.String("de", "",
"Destination to connect client's to by default.")
iniFile = flag.String("f", "none",
"Use an ini file for configuration(config file options override passed arguments for now.)")
/*targetDestination = flag.String("i", "none",
"Destination for client tunnels. Ignored for service tunnels.")*/
targetHost = flag.String("h", "127.0.0.1",
"Target host(Host of service to forward to i2p)")
targetPort = flag.String("p", "8081",
"Target port(Port of service to forward to i2p)")
targetPort443 = flag.String("tls", "",
"(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)")
peoplehash = flag.String("hashhash", "",
"32-word mnemonic representing a .b32.i2p address(will output .b32.i2p address and quit)")
samHost = flag.String("sh", "127.0.0.1",
"SAM host")
samPort = flag.String("sp", "7656",
"SAM port")
tunName = flag.String("n", "forwarder",
"Tunnel name, this must be unique but can be anything.")
accessListType = flag.String("a", "none",
"Type of access list to use, can be \"allowlist\" \"blocklist\" or \"none\".")
inLength = flag.Int("il", 3,
"Set inbound tunnel length(0 to 7)")
outLength = flag.Int("ol", 3,
"Set outbound tunnel length(0 to 7)")
inQuantity = flag.Int("iq", 6,
"Set inbound tunnel quantity(0 to 15)")
outQuantity = flag.Int("oq", 6,
"Set outbound tunnel quantity(0 to 15)")
inVariance = flag.Int("iv", 0,
"Set inbound tunnel length variance(-7 to 7)")
outVariance = flag.Int("ov", 0,
"Set outbound tunnel length variance(-7 to 7)")
inBackupQuantity = flag.Int("ib", 2,
"Set inbound tunnel backup quantity(0 to 5)")
outBackupQuantity = flag.Int("ob", 2,
"Set outbound tunnel backup quantity(0 to 5)")
reduceIdleTime = flag.Int("rt", 600000,
"Reduce tunnel quantity after X (milliseconds)")
closeIdleTime = flag.Int("ct", 600000,
"Close tunnel group after X (milliseconds)")
reduceIdleQuantity = flag.Int("rq", 3,
"Reduce idle tunnel quantity to X (0 to 5)")
readKeys = flag.String("conv", "", "Display the base32 and base64 values of a specified .i2pkeys file")
)
var (
err error
accessList flagOpts
config *i2ptunconf.Conf
)
func main() {
lb := littleboss.New("service-name")
lb.Run(func(ctx context.Context) {
lbMain(ctx)
})
}
func lbMain(ctx context.Context) {
flag.Var(&accessList, "accesslist", "Specify an access list member(can be used multiple times)")
flag.Parse()
if *readKeys != "" {
}
if *peoplehash != "" {
slice := strings.Split(*peoplehash, " ")
if length, err := strconv.Atoi(slice[len(slice)-1]); err == nil {
Hasher, err := hashhash.NewHasher(length)
if err != nil {
return
}
lhash, err := Hasher.Unfriendlyslice(slice[0 : len(slice)-2])
if err != nil {
return
}
log.Println(lhash + ".b32.i2p")
} else {
Hasher, err := hashhash.NewHasher(52)
if err != nil {
return
}
lhash, err := Hasher.Unfriendlyslice(slice)
if err != nil {
return
}
log.Println(lhash + ".b32.i2p")
}
return
}
config = &i2ptunconf.Conf{}
if *iniFile != "none" && *iniFile != "" {
config, err = i2ptunconf.NewI2PTunConf(*iniFile)
} else {
config = i2ptunconf.NewI2PBlankTunConf()
*startUp = true
}
config.TargetHost = config.GetHost(*targetHost, "127.0.0.1")
config.TargetPort = config.GetPort(*targetPort, "8081")
config.FilePath = *iniFile
config.SaveFile = config.GetSaveFile(*saveFile, true)
config.SaveDirectory = config.GetDir(*targetDir, "../")
config.SamHost = config.GetSAMHost(*samHost, "127.0.0.1")
config.SamPort = config.GetSAMPort(*samPort, "7656")
config.TunName = config.GetKeys(*tunName, "forwarder")
config.SigType = config.GetSigType(*sigType, "EdDSA_SHA512_Ed25519")
config.InLength = config.GetInLength(*inLength, 3)
config.OutLength = config.GetOutLength(*outLength, 3)
config.InVariance = config.GetInVariance(*inVariance, 0)
config.OutVariance = config.GetOutVariance(*outVariance, 0)
config.InQuantity = config.GetInQuantity(*inQuantity, 6)
config.OutQuantity = config.GetOutQuantity(*outQuantity, 6)
config.InBackupQuantity = config.GetInBackups(*inBackupQuantity, 5)
config.OutBackupQuantity = config.GetOutBackups(*outBackupQuantity, 5)
config.EncryptLeaseSet = config.GetEncryptLeaseset(*encryptLeaseSet, false)
config.LeaseSetKey = config.GetLeasesetKey(*leaseSetKey, "")
config.LeaseSetPrivateKey = config.GetLeasesetPrivateKey(*leaseSetPrivateKey, "")
config.LeaseSetPrivateSigningKey = config.GetLeasesetPrivateSigningKey(*leaseSetPrivateSigningKey, "")
config.InAllowZeroHop = config.GetInAllowZeroHop(*inAllowZeroHop, false)
config.OutAllowZeroHop = config.GetOutAllowZeroHop(*outAllowZeroHop, false)
config.UseCompression = config.GetUseCompression(*useCompression, true)
config.ReduceIdle = config.GetReduceOnIdle(*reduceIdle, true)
config.ReduceIdleTime = config.GetReduceIdleTime(*reduceIdleTime, 600000)
config.ReduceIdleQuantity = config.GetReduceIdleQuantity(*reduceIdleQuantity, 2)
config.AccessListType = config.GetAccessListType(*accessListType, "none")
config.CloseIdle = config.GetCloseOnIdle(*closeIdle, false)
config.CloseIdleTime = config.GetCloseIdleTime(*closeIdleTime, 600000)
config.Type = config.GetTypes(*client, *udpMode, *injectHeaders, "server")
config.TargetForPort443 = config.GetPort443(*targetPort443, "")
config.KeyFilePath = config.GetKeyFile(*encryptKeyFiles, "")
config.ClientDest = config.GetClientDest(*targetDest, "", "")
config.UserName = config.GetUserName(*webUser, "samcatd")
config.Password = config.GetPassword(*webPass, "")
config.ServeDirectory = config.GetWWWDir(*webDir, "./www")
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
if manager, err := sammanager.NewSAMManagerFromConf(
config,
config.TargetHost,
config.TargetPort,
config.SamHost,
config.SamPort,
"localhost",
*webPort,
*webCSS,
*webJS,
*startUp,
*webAdmin,
config.UserName,
config.Password,
); err == nil {
go func() {
for sig := range c {
if sig == os.Interrupt {
manager.Cleanup()
}
}
}()
manager.Serve()
} else {
log.Fatal(err)
}
ctx.Done()
}

Some files were not shown because too many files have changed in this diff Show More