117 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
109 changed files with 24554 additions and 6761 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@ bin/*
*.i2pkeys
*/*.i2pkeys
README.md.asc
samcatd
*/*.pem
*.pem

View File

@ -1,19 +1,18 @@
FROM alpine:3.8
FROM alpine:edge
ARG user=samcatd
ARG path=example/path
ENV samhost=sam-host
ENV samport=7656
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/samcatd
WORKDIR /usr/src/samcatd
RUN make deps full-test samcatd-web
RUN install -m755 bin/samcatd-web /usr/bin/samcatd-web
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/
CMD samcatd-web -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

211
Makefile
View File

@ -1,14 +1,13 @@
#GOPATH=$(HOME)/go
appname = ephsite
packagename = sam-forwarder
eephttpd = eephttpd
samcatd = samcatd
network = si
network = host
samhost = sam-host
samport = 7656
args = -r
USER_GH=eyedeekay
PREFIX := /
VAR := var/
@ -18,169 +17,119 @@ LOG := log/
ETC := etc/
USR := usr/
LOCAL := local/
VERSION := 0.1
VERSION := 0.32.09
WEB_INTERFACE = -tags "webface netgo"
GO111MODULE=on
echo:
@echo "$(GOPATH)"
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
find ./tcp/ -name '*.go' -exec cp -rv {} . \;
sed -i '1s|^|//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future\n|' *.go
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-serve test-vpn test
full-test: test test-serve
test-serve:
cd serve_test && go test
cd serve_test && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-ntcp:
go test
cd tcp && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-ssu:
cd udp && go test
test-vpn:
cd csvpn && go test
cd udp && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-config:
cd config && go test
cd config && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-manager:
cd manager && go test
cd manager && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
test-keys:
cd i2pkeys && go test
try-web:
cd bin && \
./samcatd-web -w -f ../etc/samcatd/tunnels.ini
gdb-web:
cd bin && \
gdb ./samcatd-web -w -f ../etc/samcatd/tunnels.ini
cd i2pkeys && go test -v -tags netgo \
-ldflags '-w -extldflags "-static"'
refresh:
deps:
go get -u github.com/songgao/water
go get -u github.com/gtank/cryptopasta
go get -u github.com/zieckey/goini
go get -u github.com/eyedeekay/udptunnel
go get -u github.com/eyedeekay/sam-forwarder/i2pkeys
go get -u github.com/eyedeekay/sam-forwarder/i2pkeys/keys
go get -u github.com/eyedeekay/sam-forwarder/tcp
go get -u github.com/eyedeekay/sam-forwarder/udp
go get -u github.com/eyedeekay/sam-forwarder/config
go get -u github.com/eyedeekay/sam-forwarder/manager
go get -u github.com/eyedeekay/sam3
go get -u github.com/eyedeekay/littleboss
go get -u github.com/eyedeekay/samcatd-web
mine:
go get -u github.com/kpetku/sam3
webdep:
go get -u github.com/eyedeekay/samcatd-web
build: clean bin/$(appname)
go get -u -d github.com/eyedeekay/sam-forwarder/samcatd
install:
install -m755 ./bin/$(appname) $(PREFIX)$(USR)$(LOCAL)/bin/
install -m755 ./bin/$(samcatd) $(PREFIX)$(USR)$(LOCAL)/bin/
install -m755 ./bin/$(samcatd)-web $(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 -m644 ./etc/i2pvpn/i2pvpn.ini $(PREFIX)$(ETC)/i2pvpn/
install -m644 ./etc/i2pvpn/i2pvpnclient.ini $(PREFIX)$(ETC)/i2pvpn/
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
daemon: clean-daemon bin/$(samcatd)
daemon-webview: bin/$(samcatd)-webview
daemon-cli: bin/$(samcatd)-cli
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
go build -a -tags netgo \
cd samcatd && go build -a -tags "netgo static" \
-ldflags '-w -extldflags "-static"' \
-o ./bin/$(samcatd) \
./daemon/*.go
-o ../bin/$(samcatd) \
./*.go
daemon-web: clean-daemon-web bin/$(samcatd)-web
bin/$(samcatd)-web:
bin/$(samcatd)-webview:
mkdir -p bin
go build -a $(WEB_INTERFACE) \
-ldflags '-w -extldflags "-static"' \
-o ./bin/$(samcatd)-web \
./daemon/*.go
cd samcatd && go build -a -tags "netgo nostatic" \
-o ../bin/$(samcatd)-webview \
./*.go
all: daemon daemon-web build server
update:
git config --global url."git@github.com:RTradeLtd".insteadOf "https://github.com/RTradeLtd"
clean-all: clean clean-server clean-daemon clean-daemon-web
all: daemon-cli daemon daemon-webview
clean:
rm -f bin/$(appname)
clean: clean-all echo
clean-server:
rm -f bin/$(eephttpd)
clean-all: clean-daemon
clean-daemon:
rm -f bin/$(samcatd)
clean-daemon-web:
rm -f bin/$(samcatd)-web
noopts: clean
mkdir -p bin
cd main && go build -o ../bin/$(appname)
rm -f bin/$(samcatd)*
install-forwarder:
install -m755 bin/ephsite /usr/local/bin/ephsite
install -m755 bin/$(samcatd) /usr/local/bin/$(samcatd)
install-server:
install -m755 bin/eephttpd /usr/local/bin/eephttpd
install-all: install install-server
remove:
rm -rf /usr/local/bin/ephsite /usr/local/bin/eephttpd
install-all: install
gendoc:
@echo "$(appname) - Easy forwarding of local services to i2p" > 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 "" >> USAGE.md
@echo "usage:" >> USAGE.md
@echo "------" >> USAGE.md
@echo "" >> USAGE.md
@echo '```' >> USAGE.md
./bin/$(appname) -help 2>> USAGE.md; true
@echo '```' >> USAGE.md
@echo "" >> USAGE.md
@echo "$(samcatd) - Router-independent tunnel management for i2p" >> USAGE.md
@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
@ -214,6 +163,7 @@ key-management:
example-config:
@echo "example config - valid for both ephsite and samcat" >> USAGE.md
@echo "==================================================" >> USAGE.md
@echo "" >> 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
@ -232,53 +182,42 @@ example-config:
docker-build:
docker build --no-cache \
--build-arg user=$(samcatd) \
--build-arg path=example/www \
docker build --build-arg user=$(samcatd) \
-f Dockerfile \
-t eyedeekay/$(samcatd) .
docker-volume:
docker run -i -t -d \
--name $(samcatd)-volume \
--volume $(samcatd):/home/$(samcatd)/ \
eyedeekay/$(samcatd); true
docker stop $(samcatd)-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 $(samcatd) \
--hostname $(samcatd) \
--name $(samcatd) \
--restart always \
--volumes-from $(samcatd)-volume \
-p 127.0.0.1:7957:7957 \
eyedeekay/$(samcatd)
make follow
c:
go build ./i2pkeys
follow:
docker logs -f $(samcatd)
docker: docker-build docker-volume docker-run
docker: docker-build docker-run
index:
pandoc USAGE.md -o example/www/index.html && cp example/www/index.html docs/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:4444 surf http://566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzuq.b32.i2p
forward:
./bin/ephsite -client -dest i2p-projekt.i2p
gojs:
go get -u github.com/gopherjs/gopherjs
@ -288,7 +227,7 @@ js:
mkdir -p bin
$(GOPHERJS) build -v --tags netgo \
-o ./javascript/$(samcatd).js \
./daemon/*.go
./samcatd/*.go
cleantar:
rm -f ../$(packagename)_$(VERSION).orig.tar.xz
@ -298,3 +237,15 @@ tar:
--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

View File

@ -1,17 +1,17 @@
# 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
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.
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.
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.
## getting
go get -u github.com/eyedeekay/sam-forwarder/samcatd
## building
Just:
make deps build
@ -30,26 +30,21 @@ There are a number of ways to use sam-forwarder:
### [encapsulate](docs/PACKAGECONF.md) configuration for i2p-enabled packages
### [implement](interface/README.md) the interface for fine-grained control over SAM connections
## binaries
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).
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.
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.
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:
====================
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 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
@ -62,20 +57,8 @@ 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.
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
@ -86,27 +69,14 @@ 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. I've started to do this with samcatd.
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 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. 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.
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. 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.
I've made it self-supervising, but I need to make better use of contexts.
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.
## Stuff that's using it:
@ -126,3 +96,12 @@ Donate
### Bitcoin Wallet Address
BTC:159M8MEUwhTzE9RXmcZxtigKaEjgfwRbHt
Index
-----
* [readme](index.html)
* [usage](usage.html)
* [configuration](packageconf.html)
* [embedding](embedding.html)
* [interface](interface.htnl)

View File

@ -58,12 +58,12 @@ key:
[*] - 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 blacklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a whitelist 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 whitelist for incoming connections. As of release 0.7.13.
[C] - i2cp.enableBlackList false Use the access list as a blacklist for incoming connections. As of release 0.7.13.
[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.blacklist null Comma- or space-separated list of Base64 peer Hashes to be blacklisted 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.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.

View File

@ -55,12 +55,12 @@ key:
[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 blacklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a whitelist 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 whitelist for incoming connections. As of release 0.7.13.
[U] - i2cp.enableBlackList false Use the access list as a blacklist for incoming connections. As of release 0.7.13.
[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.blacklist null Comma- or space-separated list of Base64 peer Hashes to be blacklisted 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.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.

View File

@ -1,6 +1,8 @@
package i2ptunconf
import "strings"
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
@ -20,20 +22,20 @@ func (c *Conf) GetAccessListType(arg, def string, label ...string) string {
func (c *Conf) SetAccessListType(label ...string) {
if v, ok := c.GetBool("i2cp.enableBlackList", label...); ok {
if v {
c.AccessListType = "blacklist"
c.AccessListType = "blocklist"
}
}
if v, ok := c.GetBool("i2cp.enableAccessList", label...); ok {
if v {
c.AccessListType = "whitelist"
c.AccessListType = "allowlist"
}
}
if c.AccessListType != "whitelist" && c.AccessListType != "blacklist" {
if c.AccessListType != "allowlist" && c.AccessListType != "blocklist" {
c.AccessListType = "none"
}
}
// AddAccessListMember adds a member to either the blacklist or the whitelist
// 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 {
@ -44,9 +46,9 @@ func (c *Conf) AddAccessListMember(key string) {
}
func (c *Conf) accesslisttype() string {
if c.AccessListType == "whitelist" {
if c.AccessListType == "allowlist" {
return "i2cp.enableAccessList=true"
} else if c.AccessListType == "blacklist" {
} else if c.AccessListType == "blocklist" {
return "i2cp.enableBlackList=true"
} else if c.AccessListType == "none" {
return ""

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 = ""
}
}

View File

@ -22,6 +22,6 @@ func (c *Conf) SetClientDest(label ...string) {
if v, ok := c.Get("destination", label...); ok {
c.ClientDest = v
} else {
c.ClientDest = v
c.ClientDest = ""
}
}

View File

@ -1,5 +1,7 @@
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

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"
}
}

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
}

View File

@ -103,3 +103,29 @@ func (c *Conf) SetLeasesetPrivateSigningKey(label ...string) {
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 = ""
}
}

View File

@ -36,7 +36,7 @@ func (c *Conf) GetOutLength(arg, def int, label ...string) int {
// SetInLength sets the inbound length from the config file
func (c *Conf) SetInLength(label ...string) {
if v, ok := c.GetInt("outbound.length", label...); ok {
if v, ok := c.GetInt("inbound.length", label...); ok {
c.OutLength = v
} else {
c.OutLength = 3
@ -45,7 +45,7 @@ func (c *Conf) SetInLength(label ...string) {
// SetOutLength sets the outbound lenth from the config file
func (c *Conf) SetOutLength(label ...string) {
if v, ok := c.GetInt("inbound.length", label...); ok {
if v, ok := c.GetInt("outbound.length", label...); ok {
c.InLength = v
} else {
c.InLength = 3

View File

@ -33,9 +33,11 @@ func (c *Conf) GetKeys(arg, def string, label ...string) string {
// SetKeys sets the key name from the config file
func (c *Conf) SetKeys(label ...string) {
if _, ok := c.Get("keys", label...); ok {
if v, ok := c.Get("keys", label...); ok {
c.TunName = v
c.SaveFile = true
} else {
c.TunName = "forwarder"
c.SaveFile = false
}
}
@ -45,6 +47,6 @@ func (c *Conf) SetTunName(label ...string) {
if v, ok := c.Get("keys", label...); ok {
c.TunName = v
} else {
c.TunName = "fowarder"
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"
}
}

View File

@ -39,7 +39,7 @@ func (c *Conf) SetInQuantity(label ...string) {
if v, ok := c.GetInt("inbound.quantity", label...); ok {
c.InQuantity = v
} else {
c.InQuantity = 5
c.InQuantity = 1
}
}
@ -48,6 +48,6 @@ func (c *Conf) SetOutQuantity(label ...string) {
if v, ok := c.GetInt("outbound.quantity", label...); ok {
c.OutQuantity = v
} else {
c.OutQuantity = 5
c.OutQuantity = 1
}
}

View File

@ -26,5 +26,8 @@ func (c *Conf) SetMessageReliability(label ...string) {
}
func (c *Conf) reliability() string {
return "i2cp.messageReliability" + c.MessageReliability
if c.MessageReliability != "" {
return "i2cp.messageReliability=" + c.MessageReliability
}
return ""
}

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"
}
}

View File

@ -1,5 +1,12 @@
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
@ -25,3 +32,80 @@ func (c *Conf) SetTargetPort443(label ...string) {
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)
}

View File

@ -1,6 +1,7 @@
package i2ptunconf
import (
// "crypto/tls"
"io/ioutil"
"log"
"os"
@ -10,58 +11,74 @@ import (
)
import (
// "github.com/eyedeekay/sam3"
"github.com/eyedeekay/sam3/i2pkeys"
"github.com/zieckey/goini"
)
// Conf is a tructure containing an ini config, with some functions to help
// when you use it for in conjunction with command-line flags
type Conf struct {
Config *goini.INI
FilePath string
KeyFilePath string
Labels []string
Client bool
ClientDest string
Type string
SaveDirectory string
SaveFile bool
TargetHost string
TargetPort string
SamHost string
SamPort string
TargetForPort443 string
TunName string
EncryptLeaseSet bool
LeaseSetKey string
LeaseSetPrivateKey string
LeaseSetPrivateSigningKey string
InAllowZeroHop bool
OutAllowZeroHop bool
InLength int
OutLength int
InQuantity int
OutQuantity int
InVariance int
OutVariance int
InBackupQuantity int
OutBackupQuantity int
UseCompression bool
FastRecieve bool
ReduceIdle bool
ReduceIdleTime int
ReduceIdleQuantity int
CloseIdle bool
CloseIdleTime int
AccessListType string
AccessList []string
MessageReliability string
exists bool
VPN bool
Config *goini.INI `default:&goini.INI{}`
FilePath string `default:"./"`
KeyFilePath string `default:"./"`
Labels []string `default:{""}`
Client bool `default:true`
ClientDest string `default:"idk.i2p"`
SigType string `default:"SIGNATURE_TYPE=EdDSA_SHA512_Ed25519"`
Type string `default:"client"`
SaveDirectory string `default:"./"`
ServeDirectory string `default:"./www"`
SaveFile bool `default:false`
TargetHost string `default:"127.0.0.1"`
TargetPort string `default:"7778"`
SamHost string `default:"127.0.0.1"`
SamPort string `default:"7656"`
TunnelHost string `default:"127.0.0.1"`
ControlHost string `default:"127.0.0.1"`
ControlPort string `default:"7951"`
TargetForPort443 string `default:""`
TunName string `default:"goi2ptunnel"`
EncryptLeaseSet bool `default:false`
LeaseSetKey string `default:""`
LeaseSetEncType string `default:"4,0"`
LeaseSetPrivateKey string `default:""`
LeaseSetPrivateSigningKey string `default:""`
InAllowZeroHop bool `default:false`
OutAllowZeroHop bool `default:false`
InLength int `default:3`
OutLength int `default:3`
InQuantity int `default:1`
OutQuantity int `default:1`
InVariance int `default:0`
OutVariance int `default:0`
InBackupQuantity int `default:1`
OutBackupQuantity int `default:1`
UseCompression bool `default:true`
FastRecieve bool `default:true`
ReduceIdle bool `default:false`
ReduceIdleTime int `default:36000000`
ReduceIdleQuantity int `default:1`
CloseIdle bool `default:false`
CloseIdleTime int `default:36000000`
AccessListType string `default:"none"`
AccessList []string `default:{""}`
MessageReliability string `default:""`
exists bool `default:false`
UserName string `default:""`
Password string `default:""`
UseTLS bool `default:false`
Cert string `default:""`
Pem string `default:""`
HostName string `default:""`
//TLSConf *tls.Config
LoadedKeys i2pkeys.I2PKeys
}
// Print returns and prints a formatted list of configured tunnel settings.
func (c *Conf) Print() []string {
// PrintSlice returns and prints a formatted list of configured tunnel settings.
func (c *Conf) PrintSlice() []string {
confstring := []string{
c.SignatureType(),
"inbound.length=" + strconv.Itoa(c.InLength),
"outbound.length=" + strconv.Itoa(c.OutLength),
"inbound.lengthVariance=" + strconv.Itoa(c.InVariance),
@ -79,14 +96,47 @@ func (c *Conf) Print() []string {
"i2cp.reduceQuantity=" + strconv.Itoa(c.ReduceIdleQuantity),
"i2cp.closeOnIdle=" + strconv.FormatBool(c.CloseIdle),
"i2cp.closeIdleTime=" + strconv.Itoa(c.CloseIdleTime),
"i2cp.fastRecieve=" + strconv.FormatBool(c.FastRecieve),
c.reliability(),
c.accesslisttype(),
c.accesslist(),
c.lsk(),
c.lspk(),
c.lsspk(),
}
log.Println(confstring)
log.Println("Tunnel:", c.TunName, "using config:", confstring)
return confstring
}
func (c *Conf) lsk() string {
if c.LeaseSetKey != "" {
return "i2cp.leaseSetKey=" + c.LeaseSetKey
}
return ""
}
func (c *Conf) lspk() string {
if c.LeaseSetPrivateKey != "" {
return "i2cp.leaseSetPrivateKey=" + c.LeaseSetPrivateKey
}
return ""
}
func (c *Conf) lsspk() string {
if c.LeaseSetPrivateSigningKey != "" {
return "i2cp.leaseSetSigningPrivateKey=" + c.LeaseSetPrivateSigningKey
}
return ""
}
func (c *Conf) SignatureType() string {
if c.SigType == "" {
return ""
}
return "SIGNATURE_TYPE=" + c.SigType
}
// Get passes directly through to goini.Get
func (c *Conf) Get(key string, label ...string) (string, bool) {
if len(c.Labels) > 0 {
@ -199,8 +249,11 @@ func (c *Conf) I2PINILoad(iniFile string, label ...string) error {
c.SetPort(label...)
c.SetSAMHost(label...)
c.SetSAMPort(label...)
c.SetEndpointHost(label...)
c.SetTunName(label...)
c.SetSigType(label...)
c.SetEncryptLease(label...)
c.SetLeaseSetEncType(label...)
c.SetLeasesetKey(label...)
c.SetLeasesetPrivateKey(label...)
c.SetLeasesetPrivateSigningKey(label...)
@ -226,6 +279,14 @@ func (c *Conf) I2PINILoad(iniFile string, label ...string) error {
c.SetMessageReliability(label...)
c.SetClientDest(label...)
c.SetKeyFile(label...)
c.SetUserName(label...)
c.SetPassword(label...)
c.SetControlHost(label...)
c.SetControlPort(label...)
c.SetWWWDir(label...)
c.SetUseTLS(label...)
c.SetTLSConfigCertPem(label...)
c.SetTLSConfigKeyPem(label...)
if v, ok := c.Get("i2cp.accessList", label...); ok {
csv := strings.Split(v, ",")
for _, z := range csv {
@ -238,9 +299,19 @@ func (c *Conf) I2PINILoad(iniFile string, label ...string) error {
// NewI2PBlankTunConf returns an empty but intialized tunconf
func NewI2PBlankTunConf() *Conf {
var c Conf
// var c Conf
c := new(Conf)
c.SamHost = "127.0.0.1"
c.SamPort = "7656"
c.TunName = "unksam"
c.TargetHost = "127.0.0.1"
c.TargetPort = "0"
c.ClientDest = "idk.i2p"
c.LeaseSetEncType = "4,0"
c.Config = &goini.INI{}
c.Config = goini.New()
return &c
c.Config.Parse([]byte("[client]\nsamhost=\"127.0.0.1\"\nsamport=\"7656\"\n"), "\n", "=")
return c
}
// NewI2PTunConf returns a Conf structure from an ini file, for modification

View File

@ -1,125 +0,0 @@
package i2ptunconf
import (
"github.com/eyedeekay/sam-forwarder/tcp"
"github.com/eyedeekay/sam-forwarder/udp"
)
// NewSAMClientForwarderFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewSAMClientForwarderFromConf(config *Conf) (*samforwarder.SAMClientForwarder, error) {
if config != nil {
return samforwarder.NewSAMClientForwarderFromOptions(
samforwarder.SetClientSaveFile(config.SaveFile),
samforwarder.SetClientFilePath(config.SaveDirectory),
samforwarder.SetClientHost(config.TargetHost),
samforwarder.SetClientPort(config.TargetPort),
samforwarder.SetClientSAMHost(config.SamHost),
samforwarder.SetClientSAMPort(config.SamPort),
samforwarder.SetClientName(config.TunName),
samforwarder.SetClientInLength(config.InLength),
samforwarder.SetClientOutLength(config.OutLength),
samforwarder.SetClientInVariance(config.InVariance),
samforwarder.SetClientOutVariance(config.OutVariance),
samforwarder.SetClientInQuantity(config.InQuantity),
samforwarder.SetClientOutQuantity(config.OutQuantity),
samforwarder.SetClientInBackups(config.InBackupQuantity),
samforwarder.SetClientOutBackups(config.OutBackupQuantity),
samforwarder.SetClientEncrypt(config.EncryptLeaseSet),
samforwarder.SetClientLeaseSetKey(config.LeaseSetKey),
samforwarder.SetClientLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samforwarder.SetClientLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samforwarder.SetClientAllowZeroIn(config.InAllowZeroHop),
samforwarder.SetClientAllowZeroOut(config.OutAllowZeroHop),
samforwarder.SetClientFastRecieve(config.FastRecieve),
samforwarder.SetClientCompress(config.UseCompression),
samforwarder.SetClientReduceIdle(config.ReduceIdle),
samforwarder.SetClientReduceIdleTimeMs(config.ReduceIdleTime),
samforwarder.SetClientReduceIdleQuantity(config.ReduceIdleQuantity),
samforwarder.SetClientCloseIdle(config.CloseIdle),
samforwarder.SetClientCloseIdleTimeMs(config.CloseIdleTime),
samforwarder.SetClientAccessListType(config.AccessListType),
samforwarder.SetClientAccessList(config.AccessList),
samforwarder.SetClientMessageReliability(config.MessageReliability),
samforwarder.SetClientPassword(config.KeyFilePath),
samforwarder.SetClientDestination(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 := 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
}
// NewSAMSSUClientForwarderFromConf generates a SAMSSUforwarder from *i2ptunconf.Conf
func NewSAMSSUClientForwarderFromConf(config *Conf) (*samforwarderudp.SAMSSUClientForwarder, error) {
if config != nil {
return samforwarderudp.NewSAMSSUClientForwarderFromOptions(
samforwarderudp.SetClientSaveFile(config.SaveFile),
samforwarderudp.SetClientFilePath(config.SaveDirectory),
samforwarderudp.SetClientHost(config.TargetHost),
samforwarderudp.SetClientPort(config.TargetPort),
samforwarderudp.SetClientSAMHost(config.SamHost),
samforwarderudp.SetClientSAMPort(config.SamPort),
samforwarderudp.SetClientName(config.TunName),
samforwarderudp.SetClientInLength(config.InLength),
samforwarderudp.SetClientOutLength(config.OutLength),
samforwarderudp.SetClientInVariance(config.InVariance),
samforwarderudp.SetClientOutVariance(config.OutVariance),
samforwarderudp.SetClientInQuantity(config.InQuantity),
samforwarderudp.SetClientOutQuantity(config.OutQuantity),
samforwarderudp.SetClientInBackups(config.InBackupQuantity),
samforwarderudp.SetClientOutBackups(config.OutBackupQuantity),
samforwarderudp.SetClientEncrypt(config.EncryptLeaseSet),
samforwarderudp.SetClientLeaseSetKey(config.LeaseSetKey),
samforwarderudp.SetClientLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samforwarderudp.SetClientLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samforwarderudp.SetClientAllowZeroIn(config.InAllowZeroHop),
samforwarderudp.SetClientAllowZeroOut(config.OutAllowZeroHop),
samforwarderudp.SetClientFastRecieve(config.FastRecieve),
samforwarderudp.SetClientCompress(config.UseCompression),
samforwarderudp.SetClientReduceIdle(config.ReduceIdle),
samforwarderudp.SetClientReduceIdleTimeMs(config.ReduceIdleTime),
samforwarderudp.SetClientReduceIdleQuantity(config.ReduceIdleQuantity),
samforwarderudp.SetClientCloseIdle(config.CloseIdle),
samforwarderudp.SetClientCloseIdleTimeMs(config.CloseIdleTime),
samforwarderudp.SetClientAccessListType(config.AccessListType),
samforwarderudp.SetClientAccessList(config.AccessList),
samforwarderudp.SetClientMessageReliability(config.MessageReliability),
samforwarderudp.SetClientPassword(config.KeyFilePath),
samforwarderudp.SetClientDestination(config.ClientDest),
)
}
return nil, nil
}
func NewSAMSSUClientForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarderudp.SAMSSUClientForwarder, error) {
if iniFile != "none" {
config, err := 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 NewSAMSSUClientForwarderFromConf(config)
}
return nil, nil
}

View File

@ -1,126 +0,0 @@
package i2ptunconf
import (
"github.com/eyedeekay/sam-forwarder/tcp"
"github.com/eyedeekay/sam-forwarder/udp"
)
// NewSAMForwarderFromConf generates a SAMforwarder from *i2ptunconf.Conf
func NewSAMForwarderFromConf(config *Conf) (*samforwarder.SAMForwarder, error) {
if config != nil {
return samforwarder.NewSAMForwarderFromOptions(
samforwarder.SetType(config.Type),
samforwarder.SetSaveFile(config.SaveFile),
samforwarder.SetFilePath(config.SaveDirectory),
samforwarder.SetHost(config.TargetHost),
samforwarder.SetPort(config.TargetPort),
samforwarder.SetSAMHost(config.SamHost),
samforwarder.SetSAMPort(config.SamPort),
samforwarder.SetName(config.TunName),
samforwarder.SetInLength(config.InLength),
samforwarder.SetOutLength(config.OutLength),
samforwarder.SetInVariance(config.InVariance),
samforwarder.SetOutVariance(config.OutVariance),
samforwarder.SetInQuantity(config.InQuantity),
samforwarder.SetOutQuantity(config.OutQuantity),
samforwarder.SetInBackups(config.InBackupQuantity),
samforwarder.SetOutBackups(config.OutBackupQuantity),
samforwarder.SetEncrypt(config.EncryptLeaseSet),
samforwarder.SetLeaseSetKey(config.LeaseSetKey),
samforwarder.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samforwarder.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samforwarder.SetAllowZeroIn(config.InAllowZeroHop),
samforwarder.SetAllowZeroOut(config.OutAllowZeroHop),
samforwarder.SetFastRecieve(config.FastRecieve),
samforwarder.SetCompress(config.UseCompression),
samforwarder.SetReduceIdle(config.ReduceIdle),
samforwarder.SetReduceIdleTimeMs(config.ReduceIdleTime),
samforwarder.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samforwarder.SetCloseIdle(config.CloseIdle),
samforwarder.SetCloseIdleTimeMs(config.CloseIdleTime),
samforwarder.SetAccessListType(config.AccessListType),
samforwarder.SetAccessList(config.AccessList),
samforwarder.SetMessageReliability(config.MessageReliability),
samforwarder.SetKeyFile(config.KeyFilePath),
//samforwarder.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 := 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
}
// NewSAMSSUForwarderFromConf generates a SAMSSUforwarder from *i2ptunconf.Conf
func NewSAMSSUForwarderFromConf(config *Conf) (*samforwarderudp.SAMSSUForwarder, error) {
if config != nil {
return samforwarderudp.NewSAMSSUForwarderFromOptions(
samforwarderudp.SetSaveFile(config.SaveFile),
samforwarderudp.SetFilePath(config.SaveDirectory),
samforwarderudp.SetHost(config.TargetHost),
samforwarderudp.SetPort(config.TargetPort),
samforwarderudp.SetSAMHost(config.SamHost),
samforwarderudp.SetSAMPort(config.SamPort),
samforwarderudp.SetName(config.TunName),
samforwarderudp.SetInLength(config.InLength),
samforwarderudp.SetOutLength(config.OutLength),
samforwarderudp.SetInVariance(config.InVariance),
samforwarderudp.SetOutVariance(config.OutVariance),
samforwarderudp.SetInQuantity(config.InQuantity),
samforwarderudp.SetOutQuantity(config.OutQuantity),
samforwarderudp.SetInBackups(config.InBackupQuantity),
samforwarderudp.SetOutBackups(config.OutBackupQuantity),
samforwarderudp.SetEncrypt(config.EncryptLeaseSet),
samforwarderudp.SetLeaseSetKey(config.LeaseSetKey),
samforwarderudp.SetLeaseSetPrivateKey(config.LeaseSetPrivateKey),
samforwarderudp.SetLeaseSetPrivateSigningKey(config.LeaseSetPrivateSigningKey),
samforwarderudp.SetAllowZeroIn(config.InAllowZeroHop),
samforwarderudp.SetAllowZeroOut(config.OutAllowZeroHop),
samforwarderudp.SetFastRecieve(config.FastRecieve),
samforwarderudp.SetCompress(config.UseCompression),
samforwarderudp.SetReduceIdle(config.ReduceIdle),
samforwarderudp.SetReduceIdleTimeMs(config.ReduceIdleTime),
samforwarderudp.SetReduceIdleQuantity(config.ReduceIdleQuantity),
samforwarderudp.SetCloseIdle(config.CloseIdle),
samforwarderudp.SetCloseIdleTimeMs(config.CloseIdleTime),
samforwarderudp.SetAccessListType(config.AccessListType),
samforwarderudp.SetAccessList(config.AccessList),
samforwarderudp.SetMessageReliability(config.MessageReliability),
samforwarderudp.SetKeyFile(config.KeyFilePath),
)
}
return nil, nil
}
// NewSAMSSUForwarderFromConfig generates a new SAMSSUForwarder from a config file
func NewSAMSSUForwarderFromConfig(iniFile, SamHost, SamPort string, label ...string) (*samforwarderudp.SAMSSUForwarder, error) {
if iniFile != "none" {
config, err := 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 NewSAMSSUForwarderFromConf(config)
}
return nil, nil
}

View File

@ -1,7 +1,6 @@
package i2ptunconf
import (
"fmt"
"strings"
)
@ -9,12 +8,15 @@ import (
// 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) GetType(argc, argu, argh bool, def string, label ...string) string {
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 {
@ -23,7 +25,44 @@ func (c *Conf) GetType(argc, argu, argh bool, def string, label ...string) strin
} 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
}
@ -42,20 +81,39 @@ func (c *Conf) SetType(label ...string) {
if strings.Contains(v, "client") {
c.Client = true
}
if strings.Contains(v, "vpn") {
c.VPN = true
}
if c.Type == "server" || c.Type == "http" || c.Type == "client" || c.Type == "udpserver" || c.Type == "udpclient" {
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 = "server"
c.Type = "browserclient"
}
}
func (c *Conf) VPNServerMode() (bool, error) {
if c.VPN == true {
return !c.Client, nil
}
return false, fmt.Errorf("VPN mode not detected.")
}

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"
}
}

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"
}
}

View File

@ -1,6 +0,0 @@
sam-forwarder for Debian
-----------------------
<possible notes regarding this package - if none, delete this file>
-- eyedeekay <hankhill19580@gmail.com> Wed, 14 Nov 2018 06:07:55 -0500

10
debian/README.source vendored
View File

@ -1,10 +0,0 @@
sam-forwarder for Debian
-----------------------
<this file describes information about the source package, see Debian policy
manual section 4.14. You WILL either need to modify or delete this file>
-- eyedeekay <hankhill19580@gmail.com> Wed, 14 Nov 2018 06:07:55 -0500

5
debian/changelog vendored
View File

@ -1,5 +0,0 @@
sam-forwarder (0.1-1) unstable; urgency=medium
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- eyedeekay <hankhill19580@gmail.com> Wed, 14 Nov 2018 06:07:55 -0500

1
debian/compat vendored
View File

@ -1 +0,0 @@
11

17
debian/control vendored
View File

@ -1,17 +0,0 @@
Source: sam-forwarder
Section: unknown
Priority: optional
Maintainer: eyedeekay <hankhill19580@gmail.com>
Build-Depends: debhelper (>= 11)
Standards-Version: 4.1.3
Homepage: https://github.com/eyedeekay/sam-forwarder
Vcs-Browser: https://github.com/eyedeekay/sam-forwarder
Vcs-Git: https://github.com/eyedeekay/sam-forwarder.git
Package: sam-forwarder
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Out-of-router i2ptunnel-like application.
sam-forwarder is a socat-inspired suite of tunneling tools for the i2p network.
It provides the same features as i2ptunnel, but does so using a router-agnostic
SAM application which accepts i2pd-like ini files and command-line parameters.

36
debian/copyright vendored
View File

@ -1,36 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: sam-forwarder
Source: <url://example.com>
Files: *
Copyright: <years> <put author's name and email here>
<years> <likewise for another author>
License: MIT
Files: debian/*
Copyright: 2018 eyedeekay <hankhill19580@gmail.com>
License: MIT
License: MIT
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 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.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid picking licenses with terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.

56
debian/manpage.1.ex vendored
View File

@ -1,56 +0,0 @@
.\" Hey, EMACS: -*- nroff -*-
.\" (C) Copyright 2018 eyedeekay <hankhill19580@gmail.com>,
.\"
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH Sam-forwarder SECTION "November 14 2018"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
sam-forwarder \- program to do something
.SH SYNOPSIS
.B sam-forwarder
.RI [ options ] " files" ...
.br
.B bar
.RI [ options ] " files" ...
.SH DESCRIPTION
This manual page documents briefly the
.B sam-forwarder
and
.B bar
commands.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
\fBsam-forwarder\fP is a program that...
.SH OPTIONS
These programs follow the usual GNU command line syntax, with long
options starting with two dashes (`-').
A summary of options is included below.
For a complete description, see the Info files.
.TP
.B \-h, \-\-help
Show summary of options.
.TP
.B \-v, \-\-version
Show version of program.
.SH SEE ALSO
.BR bar (1),
.BR baz (1).
.br
The programs are documented fully by
.IR "The Rise and Fall of a Fooish Bar" ,
available via the Info system.

154
debian/manpage.sgml.ex vendored
View File

@ -1,154 +0,0 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!-- Process this file with docbook-to-man to generate an nroff manual
page: `docbook-to-man manpage.sgml > manpage.1'. You may view
the manual page with: `docbook-to-man manpage.sgml | nroff -man |
less'. A typical entry in a Makefile or Makefile.am is:
manpage.1: manpage.sgml
docbook-to-man $< > $@
The docbook-to-man binary is found in the docbook-to-man package.
Please remember that if you create the nroff version in one of the
debian/rules file targets (such as build), you will need to include
docbook-to-man in your Build-Depends control field.
-->
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
<!ENTITY dhsurname "<surname>SURNAME</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
<!ENTITY dhdate "<date>November 14 2018</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
<!ENTITY dhemail "<email>hankhill19580@gmail.com</email>">
<!ENTITY dhusername "eyedeekay">
<!ENTITY dhucpackage "<refentrytitle>Sam-forwarder</refentrytitle>">
<!ENTITY dhpackage "sam-forwarder">
<!ENTITY debian "<productname>Debian</productname>">
<!ENTITY gnu "<acronym>GNU</acronym>">
<!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
]>
<refentry>
<refentryinfo>
<address>
&dhemail;
</address>
<author>
&dhfirstname;
&dhsurname;
</author>
<copyright>
<year>2003</year>
<holder>&dhusername;</holder>
</copyright>
&dhdate;
</refentryinfo>
<refmeta>
&dhucpackage;
&dhsection;
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>program to do something</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
<arg><option>-e <replaceable>this</replaceable></option></arg>
<arg><option>--example <replaceable>that</replaceable></option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>This manual page documents briefly the
<command>&dhpackage;</command> and <command>bar</command>
commands.</para>
<para>This manual page was written for the &debian; distribution
because the original program does not have a manual page.
Instead, it has documentation in the &gnu;
<application>Info</application> format; see below.</para>
<para><command>&dhpackage;</command> is a program that...</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<para>These programs follow the usual &gnu; command line syntax,
with long options starting with two dashes (`-'). A summary of
options is included below. For a complete description, see the
<application>Info</application> files.</para>
<variablelist>
<varlistentry>
<term><option>-h</option>
<option>--help</option>
</term>
<listitem>
<para>Show summary of options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>
<option>--version</option>
</term>
<listitem>
<para>Show version of program.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>bar (1), baz (1).</para>
<para>The programs are documented fully by <citetitle>The Rise and
Fall of a Fooish Bar</citetitle> available via the
<application>Info</application> system.</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This manual page was written by &dhusername; &dhemail; for
the &debian; system (and may be used by others). Permission is
granted to copy, distribute and/or modify this document under
the terms of the &gnu; General Public License, Version 2 any
later version published by the Free Software Foundation.
</para>
<para>
On Debian systems, the complete text of the GNU General Public
License can be found in /usr/share/common-licenses/GPL.
</para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

291
debian/manpage.xml.ex vendored
View File

@ -1,291 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!--
`xsltproc -''-nonet \
-''-param man.charmap.use.subset "0" \
-''-param make.year.ranges "1" \
-''-param make.single.year.ranges "1" \
/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \
manpage.xml'
A manual page <package>.<section> will be generated. You may view the
manual page with: nroff -man <package>.<section> | less'. A typical entry
in a Makefile or Makefile.am is:
DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl
XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
manpage.1: manpage.xml
$(XP) $(DB2MAN) $<
The xsltproc binary is found in the xsltproc package. The XSL files are in
docbook-xsl. A description of the parameters you can use can be found in the
docbook-xsl-doc-* packages. Please remember that if you create the nroff
version in one of the debian/rules file targets (such as build), you will need
to include xsltproc and docbook-xsl in your Build-Depends control field.
Alternatively use the xmlto command/package. That will also automatically
pull in xsltproc and docbook-xsl.
Notes for using docbook2x: docbook2x-man does not automatically create the
AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
<refsect1> ... </refsect1>.
To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
found in the docbook-xsl-doc-html package.
Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
General documentation about man-pages and man-page-formatting:
man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
-->
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!ENTITY dhfirstname "FIRSTNAME">
<!ENTITY dhsurname "SURNAME">
<!-- dhusername could also be set to "&dhfirstname; &dhsurname;". -->
<!ENTITY dhusername "eyedeekay">
<!ENTITY dhemail "hankhill19580@gmail.com">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1) and
http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
<!ENTITY dhsection "SECTION">
<!-- TITLE should be something like "User commands" or similar (see
http://www.tldp.org/HOWTO/Man-Page/q2.html). -->
<!ENTITY dhtitle "sam-forwarder User Manual">
<!ENTITY dhucpackage "Sam-forwarder">
<!ENTITY dhpackage "sam-forwarder">
]>
<refentry>
<refentryinfo>
<title>&dhtitle;</title>
<productname>&dhpackage;</productname>
<authorgroup>
<author>
<firstname>&dhfirstname;</firstname>
<surname>&dhsurname;</surname>
<contrib>Wrote this manpage for the Debian system.</contrib>
<address>
<email>&dhemail;</email>
</address>
</author>
</authorgroup>
<copyright>
<year>2007</year>
<holder>&dhusername;</holder>
</copyright>
<legalnotice>
<para>This manual page was written for the Debian system
(and may be used by others).</para>
<para>Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License,
Version 2 or (at your option) any later version published by
the Free Software Foundation.</para>
<para>On Debian systems, the complete text of the GNU General Public
License can be found in
<filename>/usr/share/common-licenses/GPL</filename>.</para>
</legalnotice>
</refentryinfo>
<refmeta>
<refentrytitle>&dhucpackage;</refentrytitle>
<manvolnum>&dhsection;</manvolnum>
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>program to do something</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
<!-- These are several examples, how syntaxes could look -->
<arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg>
<arg choice="opt"><option>--example=<parameter>that</parameter></option></arg>
<arg choice="opt">
<group choice="req">
<arg choice="plain"><option>-e</option></arg>
<arg choice="plain"><option>--example</option></arg>
</group>
<replaceable class="option">this</replaceable>
</arg>
<arg choice="opt">
<group choice="req">
<arg choice="plain"><option>-e</option></arg>
<arg choice="plain"><option>--example</option></arg>
</group>
<group choice="req">
<arg choice="plain"><replaceable>this</replaceable></arg>
<arg choice="plain"><replaceable>that</replaceable></arg>
</group>
</arg>
</cmdsynopsis>
<cmdsynopsis>
<command>&dhpackage;</command>
<!-- Normally the help and version options make the programs stop
right after outputting the requested information. -->
<group choice="opt">
<arg choice="plain">
<group choice="req">
<arg choice="plain"><option>-h</option></arg>
<arg choice="plain"><option>--help</option></arg>
</group>
</arg>
<arg choice="plain">
<group choice="req">
<arg choice="plain"><option>-v</option></arg>
<arg choice="plain"><option>--version</option></arg>
</group>
</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1 id="description">
<title>DESCRIPTION</title>
<para>This manual page documents briefly the
<command>&dhpackage;</command> and <command>bar</command>
commands.</para>
<para>This manual page was written for the Debian distribution
because the original program does not have a manual page.
Instead, it has documentation in the GNU <citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> format; see below.</para>
<para><command>&dhpackage;</command> is a program that...</para>
</refsect1>
<refsect1 id="options">
<title>OPTIONS</title>
<para>The program follows the usual GNU command line syntax,
with long options starting with two dashes (`-'). A summary of
options is included below. For a complete description, see the
<citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> files.</para>
<variablelist>
<!-- Use the variablelist.term.separator and the
variablelist.term.break.after parameters to
control the term elements. -->
<varlistentry>
<term><option>-e <replaceable>this</replaceable></option></term>
<term><option>--example=<replaceable>that</replaceable></option></term>
<listitem>
<para>Does this and that.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option></term>
<term><option>--help</option></term>
<listitem>
<para>Show summary of options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<term><option>--version</option></term>
<listitem>
<para>Show version of program.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="files">
<title>FILES</title>
<variablelist>
<varlistentry>
<term><filename>/etc/foo.conf</filename></term>
<listitem>
<para>The system-wide configuration file to control the
behaviour of <application>&dhpackage;</application>. See
<citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry> for further details.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>${HOME}/.foo.conf</filename></term>
<listitem>
<para>The per-user configuration file to control the
behaviour of <application>&dhpackage;</application>. See
<citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry> for further details.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="environment">
<title>ENVIRONMENT</title>
<variablelist>
<varlistentry>
<term><envar>FOO_CONF</envar></term>
<listitem>
<para>If used, the defined file is used as configuration
file (see also <xref linkend="files"/>).</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="diagnostics">
<title>DIAGNOSTICS</title>
<para>The following diagnostics may be issued
on <filename class="devicefile">stderr</filename>:</para>
<variablelist>
<varlistentry>
<term><errortext>Bad configuration file. Exiting.</errortext></term>
<listitem>
<para>The configuration file seems to contain a broken configuration
line. Use the <option>--verbose</option> option, to get more info.
</para>
</listitem>
</varlistentry>
</variablelist>
<para><command>&dhpackage;</command> provides some return codes, that can
be used in scripts:</para>
<segmentedlist>
<segtitle>Code</segtitle>
<segtitle>Diagnostic</segtitle>
<seglistitem>
<seg><errorcode>0</errorcode></seg>
<seg>Program exited successfully.</seg>
</seglistitem>
<seglistitem>
<seg><errorcode>1</errorcode></seg>
<seg>The configuration file seems to be broken.</seg>
</seglistitem>
</segmentedlist>
</refsect1>
<refsect1 id="bugs">
<!-- Or use this section to tell about upstream BTS. -->
<title>BUGS</title>
<para>The program is currently limited to only work
with the <package>foobar</package> library.</para>
<para>The upstreams <acronym>BTS</acronym> can be found
at <ulink url="http://bugzilla.foo.tld"/>.</para>
</refsect1>
<refsect1 id="see_also">
<title>SEE ALSO</title>
<!-- In alpabetical order. -->
<para><citerefentry>
<refentrytitle>bar</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>, <citerefentry>
<refentrytitle>baz</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>, <citerefentry>
<refentrytitle>foo.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry></para>
<para>The programs are documented fully by <citetitle>The Rise and
Fall of a Fooish Bar</citetitle> available via the <citerefentry>
<refentrytitle>info</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry> system.</para>
</refsect1>
</refentry>

2
debian/menu.ex vendored
View File

@ -1,2 +0,0 @@
?package(sam-forwarder):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\
title="sam-forwarder" command="/usr/bin/sam-forwarder"

39
debian/postinst.ex vendored
View File

@ -1,39 +0,0 @@
#!/bin/sh
# postinst script for sam-forwarder
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

37
debian/postrm.ex vendored
View File

@ -1,37 +0,0 @@
#!/bin/sh
# postrm script for sam-forwarder
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

35
debian/preinst.ex vendored
View File

@ -1,35 +0,0 @@
#!/bin/sh
# preinst script for sam-forwarder
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <new-preinst> `install'
# * <new-preinst> `install' <old-version>
# * <new-preinst> `upgrade' <old-version>
# * <old-preinst> `abort-upgrade' <new-version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
install|upgrade)
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

38
debian/prerm.ex vendored
View File

@ -1,38 +0,0 @@
#!/bin/sh
# prerm script for sam-forwarder
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <prerm> `remove'
# * <old-prerm> `upgrade' <new-version>
# * <new-prerm> `failed-upgrade' <old-version>
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
# * <deconfigured's-prerm> `deconfigure' `in-favour'
# <package-being-installed> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
remove|upgrade|deconfigure)
;;
failed-upgrade)
;;
*)
echo "prerm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

25
debian/rules vendored
View File

@ -1,25 +0,0 @@
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#export DH_VERBOSE = 1
# see FEATURE AREAS in dpkg-buildflags(1)
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1)
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
dh $@
# dh_make generated override targets
# This is example for Cmake (See https://bugs.debian.org/641051 )
#override_dh_auto_configure:
# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)

View File

@ -1,2 +0,0 @@
README.source
README.Debian

View File

@ -1,4 +0,0 @@
#
# Regular cron jobs for the sam-forwarder package
#
0 4 * * * root [ -x /usr/bin/sam-forwarder_maintenance ] && /usr/bin/sam-forwarder_maintenance

View File

@ -1,20 +0,0 @@
Document: sam-forwarder
Title: Debian sam-forwarder Manual
Author: <insert document author here>
Abstract: This manual describes what sam-forwarder is
and how it can be used to
manage online manuals on Debian systems.
Section: unknown
Format: debiandoc-sgml
Files: /usr/share/doc/sam-forwarder/sam-forwarder.sgml.gz
Format: postscript
Files: /usr/share/doc/sam-forwarder/sam-forwarder.ps.gz
Format: text
Files: /usr/share/doc/sam-forwarder/sam-forwarder.text.gz
Format: HTML
Index: /usr/share/doc/sam-forwarder/html/index.html
Files: /usr/share/doc/sam-forwarder/html/*.html

View File

@ -1 +0,0 @@
3.0 (quilt)

38
debian/watch.ex vendored
View File

@ -1,38 +0,0 @@
# Example watch control file for uscan
# Rename this file to "watch" and then you can run the "uscan" command
# to check for upstream updates and more.
# See uscan(1) for format
# Compulsory line, this is a version 4 file
version=4
# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig
#opts="pgpsigurlmangle=s%$%.sig%"
# HTTP site (basic)
#http://example.com/downloads.html \
# files/sam-forwarder-([\d\.]+)\.tar\.gz debian uupdate
# Uncomment to examine an FTP server
#ftp://ftp.example.com/pub/sam-forwarder-(.*)\.tar\.gz debian uupdate
# SourceForge hosted projects
# http://sf.net/sam-forwarder/ sam-forwarder-(.*)\.tar\.gz debian uupdate
# GitHub hosted projects
#opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
# https://github.com/<user>/sam-forwarder/tags \
# (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
# PyPI
# https://pypi.debian.net/sam-forwarder/sam-forwarder-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
# Direct Git
# opts="mode=git" http://git.example.com/sam-forwarder.git \
# refs/tags/v([\d\.]+) debian uupdate
# Uncomment to find new files on GooglePages
# http://example.googlepages.com/foo.html sam-forwarder-(.*)\.tar\.gz

View File

@ -1,83 +1,3 @@
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)
-headers
Inject X-I2P-DEST headers
-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)
```
samcatd - Router-independent tunnel management for i2p
=========================================================
@ -93,9 +13,7 @@ usage:
flag needs an argument: -h
Usage of ./bin/samcatd:
-a 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)
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
@ -130,6 +48,14 @@ Usage of ./bin/samcatd:
-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
@ -156,6 +82,8 @@ Usage of ./bin/samcatd:
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)

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>

View File

@ -58,12 +58,12 @@ key:
[*] - 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 blacklist. As of release 0.7.13.
[U] - i2cp.destination.sigType DSA_SHA1 Use the access list as a whitelist 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 whitelist for incoming connections. As of release 0.7.13.
[C] - i2cp.enableBlackList false Use the access list as a blacklist for incoming connections. As of release 0.7.13.
[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.blacklist null Comma- or space-separated list of Base64 peer Hashes to be blacklisted 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.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.

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>

View File

@ -1,222 +1,54 @@
<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)
-headers
Inject X-I2P-DEST headers
-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="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. It's intended to be a Swiss-army knife for the SAM API.</p>
<h2 id="usage-1">usage:</h2>
<pre><code>flag needs an argument: -h
Usage of ./bin/samcatd:
-a 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)
-c Client proxy mode(true or false)
-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)
-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;)
-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"><pre class="sourceCode ini"><code class="sourceCode ini">
<span class="co">## Defaults, these are only invoked with the -start option or if labeled tunnels</span>
<span class="co">## are not present(samcatd instructions). **THESE** are the correct config files</span>
<span class="co">## to use as defaults, and not the ones in ../sam-forwarder/tunnels.ini, which</span>
<span class="co">## are used for testing settings availability only.</span>
<span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">inbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span>
<span class="dt">outbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span>
<span class="dt">inbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">inbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span>
<span class="dt">outbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span>
<span class="dt">inbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">outbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">i2cp.encryptLeaseSet </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">gzip </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span>
<span class="dt">i2cp.reduceOnIdle </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span>
<span class="dt">i2cp.reduceIdleTime </span><span class="ot">=</span><span class="st"> </span><span class="dv">3000000</span>
<span class="dt">i2cp.reduceQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">2</span>
<span class="dt">i2cp.enableWhiteList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">i2cp.enableBlackList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">keyfile </span><span class="ot">=</span><span class="st"> &quot;/usr/share/samcatd/samcatd&quot;</span>
<span class="co">#[sam-forwarder]</span>
<span class="co">#type = server</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8081</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder</span>
<span class="kw">[sam-forwarder-two]</span>
<span class="dt">type </span><span class="ot">=</span><span class="st"> client</span>
<span class="dt">host </span><span class="ot">=</span><span class="st"> </span><span class="fl">127.0.0.1</span>
<span class="dt">port </span><span class="ot">=</span><span class="st"> </span><span class="dv">8082</span>
<span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">destination </span><span class="ot">=</span><span class="st"> i2p-projekt.i2p</span>
<span class="dt">keys </span><span class="ot">=</span><span class="st"> forwarder-two</span>
<span class="co">#[sam-forwarder-three]</span>
<span class="co">#type = udpclient</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8083</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#destination = i2p-projekt.i2p</span>
<span class="co">#keys = forwarder-three</span>
<span class="co">#[sam-forwarder-four]</span>
<span class="co">#type = udpserver</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8084</span>
<span class="co">#inbound.length = 6</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder-four</span>
<span class="co">#[sam-forwarder-five]</span>
<span class="co">#type = http</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8085</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder-five</span></code></pre></div>
<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>

9897
etc/samcatd/hashwords.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,93 +6,78 @@
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.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 = 3000000
i2cp.reduceIdleTime = 300000
i2cp.reduceQuantity = 2
i2cp.enableWhiteList = false
i2cp.enableBlackList = false
keyfile = "/usr/share/samcatd/samcatd"
#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-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 = 3
inbound.length = 2
outbound.length = 3
destination = i2p-projekt.i2p
keys = forwarder-two
keys = tcpclient
#[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-server]
type = udpserver
host = 127.0.0.1
port = 8084
inbound.length = 3
outbound.length = 3
keys = udpserver
#[sam-forwarder-udp-client]
#type = udpclient
[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 = 8083
#port = 8086
#inbound.length = 3
#outbound.length = 3
#destination = i2p-projekt.i2p
#keys = forwarder-three
#keys = proxy
#[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
[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.
*/
import (
"crypto/tls"
"flag"
"log"
"net/http"
"path/filepath"
)
import (
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/tcp"
)
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,222 +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)
-headers
Inject X-I2P-DEST headers
-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="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. It's intended to be a Swiss-army knife for the SAM API.</p>
<h2 id="usage-1">usage:</h2>
<pre><code>flag needs an argument: -h
Usage of ./bin/samcatd:
-a 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)
-c Client proxy mode(true or false)
-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)
-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;)
-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"><pre class="sourceCode ini"><code class="sourceCode ini">
<span class="co">## Defaults, these are only invoked with the -start option or if labeled tunnels</span>
<span class="co">## are not present(samcatd instructions). **THESE** are the correct config files</span>
<span class="co">## to use as defaults, and not the ones in ../sam-forwarder/tunnels.ini, which</span>
<span class="co">## are used for testing settings availability only.</span>
<span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">inbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span>
<span class="dt">outbound.lengthVariance </span><span class="ot">=</span><span class="st"> </span><span class="dv">0</span>
<span class="dt">inbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.backupQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">inbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span>
<span class="dt">outbound.quantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">5</span>
<span class="dt">inbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">outbound.allowZeroHop </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">i2cp.encryptLeaseSet </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">gzip </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span>
<span class="dt">i2cp.reduceOnIdle </span><span class="ot">=</span><span class="st"> </span><span class="kw">true</span>
<span class="dt">i2cp.reduceIdleTime </span><span class="ot">=</span><span class="st"> </span><span class="dv">3000000</span>
<span class="dt">i2cp.reduceQuantity </span><span class="ot">=</span><span class="st"> </span><span class="dv">2</span>
<span class="dt">i2cp.enableWhiteList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">i2cp.enableBlackList </span><span class="ot">=</span><span class="st"> </span><span class="kw">false</span>
<span class="dt">keyfile </span><span class="ot">=</span><span class="st"> &quot;/usr/share/samcatd/samcatd&quot;</span>
<span class="co">#[sam-forwarder]</span>
<span class="co">#type = server</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8081</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder</span>
<span class="kw">[sam-forwarder-two]</span>
<span class="dt">type </span><span class="ot">=</span><span class="st"> client</span>
<span class="dt">host </span><span class="ot">=</span><span class="st"> </span><span class="fl">127.0.0.1</span>
<span class="dt">port </span><span class="ot">=</span><span class="st"> </span><span class="dv">8082</span>
<span class="dt">inbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">outbound.length </span><span class="ot">=</span><span class="st"> </span><span class="dv">3</span>
<span class="dt">destination </span><span class="ot">=</span><span class="st"> i2p-projekt.i2p</span>
<span class="dt">keys </span><span class="ot">=</span><span class="st"> forwarder-two</span>
<span class="co">#[sam-forwarder-three]</span>
<span class="co">#type = udpclient</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8083</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#destination = i2p-projekt.i2p</span>
<span class="co">#keys = forwarder-three</span>
<span class="co">#[sam-forwarder-four]</span>
<span class="co">#type = udpserver</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8084</span>
<span class="co">#inbound.length = 6</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder-four</span>
<span class="co">#[sam-forwarder-five]</span>
<span class="co">#type = http</span>
<span class="co">#host = 127.0.0.1</span>
<span class="co">#port = 8085</span>
<span class="co">#inbound.length = 3</span>
<span class="co">#outbound.length = 3</span>
<span class="co">#keys = forwarder-five</span></code></pre></div>

View File

@ -1,392 +0,0 @@
//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future
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 save the tunnel keys long-term
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 TCP Client 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
}
}
//SetClientLeaseSetKey sets
func SetClientLeaseSetKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetKey = s
return nil
}
}
//SetClientLeaseSetPrivateKey sets
func SetClientLeaseSetPrivateKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetPrivateKey = s
return nil
}
}
//SetClientLeaseSetPrivateSigningKey sets
func SetClientLeaseSetPrivateSigningKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetPrivateSigningKey = s
return nil
}
}
//SetClientMessageReliability sets
func SetClientMessageReliability(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.messageReliability = s
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
}
}
//SetClientFastRecieve tells clients use the i2cp.fastRecieve option
func SetClientFastRecieve(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.fastRecieve = "true"
return nil
}
c.fastRecieve = "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 = "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 = "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 nil
}
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
}
}
//SetKeyFile sets
func SetClientPassword(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.passfile = s
return nil
}
}

View File

@ -1,315 +0,0 @@
//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future
package samforwarder
import (
"io"
"log"
"net"
//"os"
//"path/filepath"
"strings"
)
import (
"github.com/eyedeekay/sam-forwarder/i2pkeys"
"github.com/eyedeekay/sam3"
"github.com/eyedeekay/sam3/i2pkeys"
)
// SAMClientForwarder is a tcp proxy that automatically forwards ports to i2p
type SAMClientForwarder struct {
SamHost string
SamPort string
TunName string
Type string
TargetHost string
TargetPort string
samConn *sam3.SAM
SamKeys i2pkeys.I2PKeys
connectStream *sam3.StreamSession
dest string
addr i2pkeys.I2PAddr
publishConnection net.Listener
FilePath string
file io.ReadWriter
save bool
// samcatd options
passfile string
// I2CP options
encryptLeaseSet string
leaseSetKey string
leaseSetPrivateKey string
leaseSetPrivateSigningKey string
LeaseSetKeys *i2pkeys.I2PKeys
inAllowZeroHop string
outAllowZeroHop string
inLength string
outLength string
inQuantity string
outQuantity string
inVariance string
outVariance string
inBackupQuantity string
outBackupQuantity string
fastRecieve string
useCompression string
messageReliability string
closeIdle string
closeIdleTime string
reduceIdle string
reduceIdleTime string
reduceIdleQuantity string
//Streaming Library options
accessListType string
accessList []string
}
func (f *SAMClientForwarder) ID() string {
return f.TunName
}
func (f *SAMClientForwarder) print() []string {
lsk, lspk, lspsk := f.leasesetsettings()
return []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.fastRecieve=" + f.fastRecieve,
"i2cp.gzip=" + f.useCompression,
"i2cp.reduceOnIdle=" + f.reduceIdle,
"i2cp.reduceIdleTime=" + f.reduceIdleTime,
"i2cp.reduceQuantity=" + f.reduceIdleQuantity,
"i2cp.closeOnIdle=" + f.closeIdle,
"i2cp.closeIdleTime=" + f.closeIdleTime,
"i2cp.messageReliability" + f.messageReliability,
"i2cp.encryptLeaseSet=" + f.encryptLeaseSet,
lsk, lspk, lspsk,
f.accesslisttype(),
f.accesslist(),
}
}
func (f *SAMClientForwarder) Cleanup() {
f.connectStream.Close()
f.publishConnection.Close()
f.samConn.Close()
}
func (f *SAMClientForwarder) Print() string {
var r string
r += "name=" + f.TunName + "\n"
r += "type=" + f.Type + "\n"
r += "base32=" + f.Base32() + "\n"
r += "base64=" + f.Base64() + "\n"
r += "dest=" + f.dest + "\n"
r += "ntcpclient\n"
for _, s := range f.print() {
r += s + "\n"
}
return strings.Replace(r, "\n\n", "\n", -1)
return r
}
func (f *SAMClientForwarder) 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 *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 ""
}
func (f *SAMClientForwarder) 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 *SAMClientForwarder) Target() string {
return f.TargetHost + ":" + f.TargetPort
}
// Destination returns the destination of the i2p service you want to forward locally
func (f *SAMClientForwarder) Destination() string {
return f.addr.Base32()
}
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() error {
if f.addr, err = f.samConn.Lookup(f.dest); err != nil {
return err
}
if f.connectStream, err = f.samConn.NewStreamSession(f.TunName, f.SamKeys, f.print()); 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)
}
}
//Close shuts the whole thing down.
func (f *SAMClientForwarder) Close() error {
var err error
err = f.samConn.Close()
err = f.connectStream.Close()
err = f.publishConnection.Close()
return err
}
//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 = "2"
s.outQuantity = "2"
s.inVariance = "1"
s.outVariance = "1"
s.inBackupQuantity = "3"
s.outBackupQuantity = "3"
s.inAllowZeroHop = "false"
s.outAllowZeroHop = "false"
s.encryptLeaseSet = "false"
s.leaseSetKey = ""
s.leaseSetPrivateKey = ""
s.leaseSetPrivateSigningKey = ""
s.fastRecieve = "false"
s.useCompression = "true"
s.reduceIdle = "false"
s.reduceIdleTime = "300000"
s.reduceIdleQuantity = "4"
s.closeIdle = "false"
s.closeIdleTime = "300000"
s.dest = "none"
s.Type = "client"
s.messageReliability = "none"
s.passfile = ""
s.dest = "i2p-projekt.i2p"
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.save {
log.Println("Saving i2p keys")
}
if s.SamKeys, err = sfi2pkeys.Load(s.FilePath, s.TunName, s.passfile, s.samConn, s.save); err != nil {
return nil, err
}
log.Println("Destination keys generated, tunnel name:", s.TunName)
if s.save {
if err := sfi2pkeys.Save(s.FilePath, s.TunName, s.passfile, s.SamKeys); err != nil {
return nil, err
}
log.Println("Saved tunnel keys for", s.TunName)
}
return &s, nil
}

View File

@ -1,413 +0,0 @@
//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future
package samforwarder
import (
"fmt"
"strconv"
)
//Option is a SAMForwarder Option
type Option func(*SAMForwarder) error
//SetFilePath sets the path to save the config file at.
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 {
c.Type = "server"
return nil
}
}
}
//SetSaveFile tells the router to save the tunnel's keys long-term
func SetSaveFile(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.save = b
return nil
}
}
//SetHost sets the host of the service to forward
func SetHost(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.TargetHost = s
return nil
}
}
//SetPort sets the port of the service to forward
func SetPort(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) 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.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
}
}
//SetLeaseSetKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetKey = s
return nil
}
}
//SetLeaseSetPrivateKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetPrivateKey = s
return nil
}
}
//SetLeaseSetPrivateSigningKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateSigningKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetPrivateSigningKey = s
return nil
}
}
//SetMessageReliability sets the host of the SAMForwarder's SAM bridge
func SetMessageReliability(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.messageReliability = s
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
}
}
//SetFastRecieve tells clients to use compression
func SetFastRecieve(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.fastRecieve = "true"
return nil
}
c.fastRecieve = "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 = "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 = "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 = "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 = "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 nil
}
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")
}
}
*/
//SetKeyFile sets
func SetKeyFile(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.passfile = s
return nil
}
}

View File

@ -1,420 +0,0 @@
//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future
package samforwarder
import (
"bufio"
"io"
"log"
"net"
"net/http"
"net/http/httputil"
//"os"
//"path/filepath"
"strings"
)
import (
"github.com/eyedeekay/sam-forwarder/i2pkeys"
"github.com/eyedeekay/sam3"
"github.com/eyedeekay/sam3/i2pkeys"
)
//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 i2pkeys.I2PKeys
publishStream *sam3.StreamSession
publishListen *sam3.StreamListener
publishConnection net.Conn
FilePath string
file io.ReadWriter
save bool
Type string
// samcatd options
passfile string
// I2CP options
encryptLeaseSet string
leaseSetKey string
leaseSetPrivateKey string
leaseSetPrivateSigningKey string
LeaseSetKeys *i2pkeys.I2PKeys
inAllowZeroHop string
outAllowZeroHop string
inLength string
outLength string
inQuantity string
outQuantity string
inVariance string
outVariance string
inBackupQuantity string
outBackupQuantity string
fastRecieve string
useCompression string
messageReliability string
closeIdle string
closeIdleTime string
reduceIdle string
reduceIdleTime string
reduceIdleQuantity string
//Streaming Library options
accessListType string
accessList []string
clientLock bool
connLock bool
connClientLock bool
connConnLock bool
}
var err error
func (f *SAMForwarder) ID() string {
return f.TunName
}
func (f *SAMForwarder) Cleanup() {
f.publishStream.Close()
f.publishListen.Close()
f.publishConnection.Close()
f.samConn.Close()
}
/*func (f *SAMForwarder) targetForPort443() string {
if f.TargetForPort443 != "" {
return "targetForPort.4443=" + f.TargetHost + ":" + f.TargetForPort443
}
return ""
}*/
func (f *SAMForwarder) print() []string {
lsk, lspk, lspsk := f.leasesetsettings()
return []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.fastRecieve=" + f.fastRecieve,
"i2cp.gzip=" + f.useCompression,
"i2cp.reduceOnIdle=" + f.reduceIdle,
"i2cp.reduceIdleTime=" + f.reduceIdleTime,
"i2cp.reduceQuantity=" + f.reduceIdleQuantity,
"i2cp.closeOnIdle=" + f.closeIdle,
"i2cp.closeIdleTime=" + f.closeIdleTime,
"i2cp.messageReliability" + f.messageReliability,
"i2cp.encryptLeaseSet=" + f.encryptLeaseSet,
lsk, lspk, lspsk,
f.accesslisttype(),
f.accesslist(),
}
}
func (f *SAMForwarder) Print() string {
var r string
r += "name=" + f.TunName + "\n"
r += "type=" + f.Type + "\n"
r += "base32=" + f.Base32() + "\n"
r += "base64=" + f.Base64() + "\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 *SAMForwarder) 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 *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 ""
}
func (f *SAMForwarder) 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 *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, *http.Request, error) {
var request *http.Request
var retrequest []byte
var err error
request, err = http.ReadRequest(bufio.NewReader(conn))
if err != nil {
return nil, nil, err
}
dest := conn.RemoteAddr().(i2pkeys.I2PAddr)
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, nil, err
}
return retrequest, request, nil
}
func (f *SAMForwarder) HTTPResponseBytes(conn net.Conn, req *http.Request) ([]byte, error) {
var response *http.Response
var retresponse []byte
var err error
response, err = http.ReadResponse(bufio.NewReader(conn), req)
if err != nil {
return nil, err
}
response.Header.Add("X-I2p-Dest-Base64", f.Base64())
response.Header.Add("X-I2p-Dest-Base32", f.Base32())
if retresponse, err = httputil.DumpResponse(response, true); err != nil {
return nil, err
}
return retresponse, nil
}
func (f *SAMForwarder) clientUnlockAndClose(cli, conn bool, client net.Conn) {
if cli {
f.clientLock = cli
}
if conn {
f.connLock = conn
}
if f.clientLock && f.connLock {
client.Close()
f.clientLock = false
f.connLock = false
}
}
func (f *SAMForwarder) connUnlockAndClose(cli, conn bool, connection *sam3.SAMConn) {
if cli {
f.connClientLock = cli
}
if conn {
f.connConnLock = conn
}
if f.connClientLock && f.connConnLock {
connection.Close()
f.connClientLock = false
f.connConnLock = false
}
}
func (f *SAMForwarder) forward(conn *sam3.SAMConn) { //(conn net.Conn) {
var request *http.Request
var requestbytes []byte
var responsebytes []byte
var err error
var client net.Conn
if client, err = net.Dial("tcp", f.Target()); err != nil {
log.Fatalf("Dial failed: %v", err)
}
go func() {
if f.Type == "http" {
defer f.clientUnlockAndClose(true, false, client)
defer f.connUnlockAndClose(false, true, conn)
if requestbytes, request, err = f.HTTPRequestBytes(conn); err == nil {
log.Printf("Forwarding modified request: \n\t %s", string(requestbytes))
client.Write(requestbytes)
} else {
log.Println("Error: ", requestbytes, err)
}
} else {
defer client.Close()
defer conn.Close()
io.Copy(client, conn)
}
}()
go func() {
if f.Type == "http" {
defer f.clientUnlockAndClose(false, true, client)
defer f.connUnlockAndClose(true, false, conn)
if responsebytes, err = f.HTTPResponseBytes(client, request); err == nil {
log.Printf("Forwarding modified response: \n\t%s", string(responsebytes))
conn.Write(responsebytes)
} else {
log.Println("Response Error: ", responsebytes, err)
}
} else {
defer client.Close()
defer conn.Close()
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 {
//lsk, lspk, lspsk := f.leasesetsettings()
if f.publishStream, err = f.samConn.NewStreamSession(f.TunName, f.SamKeys, f.print()); 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)
}
}
//Close shuts the whole thing down.
func (f *SAMForwarder) Close() error {
var err error
err = f.samConn.Close()
err = f.publishStream.Close()
err = f.publishListen.Close()
err = f.publishConnection.Close()
return err
}
//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.Type = "server"
s.inLength = "3"
s.outLength = "3"
s.inQuantity = "2"
s.outQuantity = "2"
s.inVariance = "1"
s.outVariance = "1"
s.inBackupQuantity = "3"
s.outBackupQuantity = "3"
s.inAllowZeroHop = "false"
s.outAllowZeroHop = "false"
s.encryptLeaseSet = "false"
s.leaseSetKey = ""
s.leaseSetPrivateKey = ""
s.leaseSetPrivateSigningKey = ""
s.fastRecieve = "false"
s.useCompression = "true"
s.reduceIdle = "false"
s.reduceIdleTime = "15"
s.reduceIdleQuantity = "4"
s.closeIdle = "false"
s.closeIdleTime = "300000"
s.clientLock = false
s.connLock = false
s.messageReliability = "none"
s.passfile = ""
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.save {
log.Println("Saving i2p keys")
}
if s.SamKeys, err = sfi2pkeys.Load(s.FilePath, s.TunName, s.passfile, s.samConn, s.save); err != nil {
return nil, err
}
log.Println("Destination keys generated, tunnel name:", s.TunName)
if s.save {
if err := sfi2pkeys.Save(s.FilePath, s.TunName, s.passfile, s.SamKeys); err != nil {
return nil, err
}
log.Println("Saved tunnel keys for", s.TunName)
}
return &s, nil
}

View File

@ -1,287 +0,0 @@
//AUTO-GENERATED FOR BACKWARD COMPATIBILITY, USE ./tcp in the future
package samforwarder
import (
"log"
"testing"
)
func TestOptionHost(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetHost("127.0.0.1"))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionPort(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetPort("8080"))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionInLength(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetInLength(3))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionOutLength(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetInLength(3))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionInVariance(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetInVariance(1))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionOutVariance(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetOutVariance(1))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionInQuantity(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetInQuantity(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionOutQuantity(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetOutQuantity(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionInBackups(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetInBackups(5))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionOutBackups(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetOutBackups(5))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionReduceIdleQuantity(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetReduceIdleQuantity(4))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionReduceIdleTimeMs(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetReduceIdleTimeMs(300000))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionReduceIdleTime(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetReduceIdleTime(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionCloseIdleTimeMs(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetCloseIdleTimeMs(300000))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionCloseIdleTime(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetCloseIdleTime(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionEncryptLease(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetEncrypt(true))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestOptionSaveFile(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetSaveFile(true))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionHost(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientHost("127.0.0.1"))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionPort(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientSAMPort("7656"))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionInLength(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientInLength(3))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionOutLength(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientInLength(3))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionInVariance(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientInVariance(1))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionOutVariance(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientOutVariance(1))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionInQuantity(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientInQuantity(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionOutQuantity(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientOutQuantity(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionInBackups(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientInBackups(5))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionOutBackups(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientOutBackups(5))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionReduceIdleQuantity(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientReduceIdleQuantity(4))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionReduceIdleTimeMs(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientReduceIdleTimeMs(300000))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionReduceIdleTime(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientReduceIdleTime(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionCloseIdleTimeMs(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientCloseIdleTimeMs(300000))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionCloseIdleTime(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientCloseIdleTime(6))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionEncryptLease(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientEncrypt(true))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
func TestClientOptionSaveFile(t *testing.T) {
client, err := NewSAMClientForwarderFromOptions(SetClientSaveFile(true))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}
/*func TestOptionTargetForPort443(t *testing.T) {
client, err := NewSAMForwarderFromOptions(SetTargetForPort443("443"))
if err != nil {
t.Fatalf("NewSAMForwarder() Error: %q\n", err)
}
log.Println(client.Base32())
}*/

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
}

View File

@ -4,6 +4,7 @@ import (
"log"
"os"
"path/filepath"
"strings"
"github.com/eyedeekay/sam-forwarder/i2pkeys/keys"
//"github.com/eyedeekay/sam-forwarder/i2pkeys/password"
@ -78,3 +79,16 @@ func Load(FilePath, TunName, passfile string, samConn *sam3.SAM, save bool) (i2p
//}
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
}

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)
}
```

View File

@ -1,15 +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 {
//GetType() string
Cleanup()
// 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,45 +0,0 @@
package main
import (
"log"
"os"
"os/signal"
)
import "github.com/eyedeekay/sam-forwarder/config"
func clientMode() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
if *udpMode {
log.Println("Proxying udp", *targetHost+":"+*targetPort, "to", *targetDestination)
forwarder, err := i2ptunconf.NewSAMSSUClientForwarderFromConf(config)
if err == nil {
forwarder.Serve()
} else {
log.Println(err.Error())
}
go func() {
for sig := range c {
if sig == os.Interrupt {
forwarder.Cleanup()
}
}
}()
} else {
log.Println("Proxying tcp", *targetHost+":"+*targetPort, "to", *targetDestination)
forwarder, err := i2ptunconf.NewSAMClientForwarderFromConf(config)
if err == nil {
forwarder.Serve()
} else {
log.Println(err.Error())
}
go func() {
for sig := range c {
if sig == os.Interrupt {
forwarder.Cleanup()
}
}
}()
}
}

View File

@ -1,120 +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, "")
config.ClientDest = config.GetClientDest(*targetDestination, "", "")
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,45 +0,0 @@
package main
import (
"log"
"os"
"os/signal"
)
import "github.com/eyedeekay/sam-forwarder/config"
func serveMode() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
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())
}
go func() {
for sig := range c {
if sig == os.Interrupt {
forwarder.Cleanup()
}
}
}()
} else {
log.Println("Redirecting tcp", *targetHost+":"+*targetPort, "to i2p")
forwarder, err := i2ptunconf.NewSAMForwarderFromConf(config)
if err == nil {
forwarder.Serve()
} else {
log.Println(err.Error())
}
go func() {
for sig := range c {
if sig == os.Interrupt {
forwarder.Cleanup()
}
}
}()
}
}

View File

@ -13,15 +13,7 @@ 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.FilePath = s
return nil
}
}
//SetManagerSaveFile tells the router to use an encrypted leaseset
func SetManagerSaveFile(b bool) func(*SAMManager) error {
return func(c *SAMManager) error {
c.save = b
c.config.FilePath = s
return nil
}
}
@ -34,6 +26,22 @@ func SetManagerHost(s string) func(*SAMManager) error {
}
}
//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 {
@ -111,6 +119,14 @@ func SetManagerStart(s bool) func(*SAMManager) error {
}
}
//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 {

View File

@ -1,23 +1,25 @@
package sammanager
import (
"fmt"
//"fmt"
"log"
"strings"
"os/exec"
"os/user"
"runtime"
"strconv"
)
import (
"github.com/eyedeekay/portcheck"
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/interface"
"github.com/eyedeekay/sam-forwarder/tcp"
//"github.com/eyedeekay/sam-forwarder/udp"
"github.com/eyedeekay/sam-forwarder/config/helpers"
"github.com/eyedeekay/sam-forwarder/handler"
"github.com/justinas/nosurf"
)
type SAMManager struct {
FilePath string
save bool
start bool
config *i2ptunconf.Conf
start bool
config *i2ptunconf.Conf
tunName string
@ -25,114 +27,71 @@ type SAMManager struct {
ServerPort string
SamHost string
SamPort string
UseWeb bool
WebHost string
WebPort string
tunnels []samtunnel.SAMTunnel
cssFile string
jsFile string
handlerMux *samtunnelhandler.TunnelHandlerMux
}
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.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.tunnels {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Print()))
}
return &r
case "ntcpserver":
for index, element := range s.tunnels {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "httpserver":
for index, element := range s.tunnels {
if element.(*samforwarder.SAMForwarder).Type == "http" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
return &r
case "ntcpclient":
for index, element := range s.tunnels {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "ssuserver":
for index, element := range s.tunnels {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
case "ssuclient":
for index, element := range s.tunnels {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
return &r
default:
for index, element := range s.tunnels {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.tunnels {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.tunnels {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
for index, element := range s.tunnels {
if element.Search(stringify(search)) != "" {
r = append(r, fmt.Sprintf(" %v. %s", index, element.Search(stringify(search))))
}
}
return &r
}
}
return &r
}
var err error
func (s *SAMManager) Cleanup() {
for _, k := range s.tunnels {
for _, k := range s.handlerMux.Tunnels() {
k.Cleanup()
}
}
func (s *SAMManager) Serve() bool {
log.Println("Starting tunnels")
for _, element := range s.tunnels {
log.Println("Starting service tunnel", element.ID())
go element.Serve()
}
for true {
}
return false
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.FilePath = ""
s.save = true
s.start = false
s.config = i2ptunconf.NewI2PBlankTunConf()
s.config.FilePath = ""
s.start = false
s.UseWeb = true
s.ServerHost = "localhost"
s.ServerPort = "8081"
s.SamHost = "localhost"
@ -140,129 +99,234 @@ func NewSAMManagerFromOptions(opts ...func(*SAMManager) error) (*SAMManager, err
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("tunnel settings", s.ServerHost, s.ServerPort, s.SamHost, s.SamPort)
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.FilePath != "" {
s.config, err = i2ptunconf.NewI2PTunConf(s.FilePath)
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
}
} else {
if s.config == nil {
return nil, fmt.Errorf("Configuration not found")
}
s.FilePath = s.config.FilePath
}
for _, label := range s.config.Labels {
if t, e := s.config.Get("type", label); e {
switch t {
case "http":
if f, e := i2ptunconf.NewSAMForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found http under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
}
case "server":
if f, e := i2ptunconf.NewSAMForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found server under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
}
case "client":
if f, e := i2ptunconf.NewSAMClientForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found client under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
}
case "udpserver":
if f, e := i2ptunconf.NewSAMSSUForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found udpserver under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
}
case "udpclient":
if f, e := i2ptunconf.NewSAMSSUClientForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found udpclient under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
}
default:
if f, e := i2ptunconf.NewSAMForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort, label); e == nil {
log.Println("found server under", label)
s.tunnels = append(s.tunnels, f)
} else {
return nil, fmt.Errorf(e.Error())
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
}
}
}
}
}
if len(s.config.Labels) == 0 || s.start {
} else {
t, b := s.config.Get("type")
if !b {
t = "client"
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 := i2ptunconf.NewSAMForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConf(s.config)); e == nil {
log.Println("found default http")
s.tunnels = append(s.tunnels, f)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, fmt.Errorf(e.Error())
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 := i2ptunconf.NewSAMForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMForwarderFromConf(s.config)); e == nil {
log.Println("found default server")
s.tunnels = append(s.tunnels, f)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, fmt.Errorf(e.Error())
return nil, e
}
case "client":
if f, e := i2ptunconf.NewSAMClientForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMClientForwarderFromConf(s.config)); e == nil {
log.Println("found default client")
s.tunnels = append(s.tunnels, f)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, fmt.Errorf(e.Error())
return nil, e
}
case "udpserver":
if f, e := i2ptunconf.NewSAMSSUForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGForwarderFromConf(s.config)); e == nil {
log.Println("found default udpserver")
s.tunnels = append(s.tunnels, f)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, fmt.Errorf(e.Error())
return nil, e
}
case "udpclient":
if f, e := i2ptunconf.NewSAMSSUClientForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
if f, e := samtunnelhandler.NewTunnelHandler(i2ptunhelper.NewSAMDGClientForwarderFromConf(s.config)); e == nil {
log.Println("found default udpclient")
s.tunnels = append(s.tunnels, f)
s.handlerMux = s.handlerMux.Append(f)
} else {
return nil, fmt.Errorf(e.Error())
return nil, e
}
default:
if f, e := i2ptunconf.NewSAMClientForwarderFromConfig(s.FilePath, s.SamHost, s.SamPort); e == nil {
log.Println("found default client")
s.tunnels = append(s.tunnels, f)
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, fmt.Errorf(e.Error())
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 string, start bool) (*SAMManager, error) {
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),
@ -273,10 +337,13 @@ func NewSAMManager(inifile, servhost, servport, samhost, samport, webhost, webpo
SetManagerWebHost(webhost),
SetManagerWebPort(webport),
SetManagerStart(start),
SetManagerWebUser(webuser),
SetManagerWebPass(webpass),
SetManagerWeb(web),
)
}
func NewSAMManagerFromConf(conf *i2ptunconf.Conf, servhost, servport, samhost, samport, webhost, webport string, start bool) (*SAMManager, error) {
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),
@ -287,5 +354,8 @@ func NewSAMManagerFromConf(conf *i2ptunconf.Conf, servhost, servport, samhost, s
SetManagerWebHost(webhost),
SetManagerWebPort(webport),
SetManagerStart(start),
SetManagerWebUser(webuser),
SetManagerWebPass(webpass),
SetManagerWeb(web),
)
}

View File

@ -1,10 +1,91 @@
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"),

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

View File

@ -6,14 +6,15 @@ import (
"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"
"github.com/eyedeekay/samcatd-web"
)
type flagOpts []string
@ -57,21 +58,29 @@ var (
reduceIdle = flag.Bool("r", false,
"Reduce tunnel quantity when idle(true or false)")
closeIdle = flag.Bool("x", false,
"Close tunnel idle(true or 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", false,
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",
@ -84,14 +93,16 @@ var (
"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.")
/*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",
@ -99,7 +110,7 @@ var (
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 \"whitelist\" \"blacklist\" or \"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,
@ -119,18 +130,16 @@ var (
reduceIdleTime = flag.Int("rt", 600000,
"Reduce tunnel quantity after X (milliseconds)")
closeIdleTime = flag.Int("ct", 600000,
"Reduce tunnel quantity after X (milliseconds)")
"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 (
webinterface *samcatweb.SAMWebConfig
webinterfaceerr error
err error
accessList flagOpts
config *i2ptunconf.Conf
err error
accessList flagOpts
config *i2ptunconf.Conf
)
func main() {
@ -148,19 +157,48 @@ func lbMain(ctx context.Context) {
}
config = i2ptunconf.NewI2PBlankTunConf()
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)
@ -182,10 +220,13 @@ func lbMain(ctx context.Context) {
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.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)
@ -198,7 +239,12 @@ func lbMain(ctx context.Context) {
config.SamPort,
"localhost",
*webPort,
*webCSS,
*webJS,
*startUp,
*webAdmin,
config.UserName,
config.Password,
); err == nil {
go func() {
for sig := range c {
@ -207,9 +253,6 @@ func lbMain(ctx context.Context) {
}
}
}()
if *webAdmin {
go samcatweb.Serve(manager, "", "", manager.WebHost, manager.WebPort)
}
manager.Serve()
} else {
log.Fatal(err)

View File

@ -18,9 +18,9 @@ import (
var (
port = "8100"
cport = "8101"
uport = "8102"
ucport = "8103"
ssuport = "8104"
UDPServerPort = "8102"
UDPClientPort = "8103"
SSUServerPort = "8104"
udpserveraddr *net.UDPAddr
udplocaladdr *net.UDPAddr
ssulocaladdr *net.UDPAddr
@ -75,12 +75,12 @@ func client() {
}
func echo() {
/* Lets prepare a address at any address at port 10001*/
udpserveraddr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+uport)
/* Lets prepare a address at any address at port UDPServerPort */
udpserveraddr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+UDPServerPort)
if err != nil {
log.Fatal(err)
}
fmt.Println("listening on :", uport)
fmt.Println("starting UDP echo server listening on :", UDPServerPort)
/* Now listen at selected port */
udpserverconn, err = net.ListenUDP("udp", udpserveraddr)
@ -102,12 +102,18 @@ func echo() {
}
}
func serveudp() {
flag.Parse()
func echoclient() {
udpclientaddr, e := net.Dial("udp", "127.0.0.1:"+UDPServerPort)
if e != nil {
log.Fatal(e)
}
udpclientaddr.Write([]byte("test"))
}
ssuforwarder, err = samforwarderudp.NewSAMSSUForwarderFromOptions(
func serveudp() {
ssuforwarder, err = samforwarderudp.NewSAMDGForwarderFromOptions(
samforwarderudp.SetHost("127.0.0.1"),
samforwarderudp.SetPort(uport),
samforwarderudp.SetPort(UDPServerPort),
samforwarderudp.SetSAMHost("127.0.0.1"),
samforwarderudp.SetSAMPort("7656"),
samforwarderudp.SetName("testudpserver"),
@ -115,16 +121,18 @@ func serveudp() {
if err != nil {
log.Fatal(err.Error())
}
go ssuforwarder.Serve()
log.Printf("Serving on UDP port: %s and on %s\n", uport, ssuforwarder.Base32())
f, e := ssuforwarder.Load()
if e != nil {
log.Fatal(e.Error())
}
go f.Serve()
log.Printf("Serving on UDP port: %s and on %s\n", UDPServerPort, ssuforwarder.Base32())
}
func clientudp() {
flag.Parse()
ssuforwarderclient, err = samforwarderudp.NewSAMSSUClientForwarderFromOptions(
ssuforwarderclient, err = samforwarderudp.NewSAMDGClientForwarderFromOptions(
samforwarderudp.SetClientHost("127.0.0.1"),
samforwarderudp.SetClientPort(ssuport),
samforwarderudp.SetClientPort(UDPClientPort),
samforwarderudp.SetClientSAMHost("127.0.0.1"),
samforwarderudp.SetClientSAMPort("7656"),
samforwarderudp.SetClientName("testudpclient"),
@ -133,17 +141,22 @@ func clientudp() {
if err != nil {
log.Fatal(err.Error())
}
go ssuforwarderclient.Serve()
log.Printf("Connecting UDP port: %s to %s\n", ssuport, ssuforwarder.Base32())
f, e := ssuforwarderclient.Load()
if e != nil {
log.Fatal(e.Error())
}
go f.Serve()
log.Printf("Connecting UDP port: %s to %s\n", SSUServerPort, ssuforwarder.Base32())
}
func setupudp() {
ssulocaladdr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+ssuport)
ssulocaladdr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+SSUServerPort)
if err != nil {
log.Fatal(err)
}
udplocaladdr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+ucport)
udplocaladdr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"+UDPClientPort)
if err != nil {
log.Fatal(err)
}

View File

@ -3,26 +3,27 @@ package samforwardertest
import (
"log"
"net"
"net/http"
//"net/http"
"testing"
"time"
)
var longcount = 60
func countdown(i int) {
for i > 0 {
time.Sleep(1 * time.Second)
i--
log.Println("waiting", i, "more seconds.")
if i%10 == 0 {
log.Println("Waiting", i, "more seconds.")
}
}
}
/*
func TestTCP(t *testing.T) {
go serve()
countdown(longcount)
countdown(61)
go client()
countdown(longcount)
countdown(61)
resp, err := http.Get("http://127.0.0.1:" + cport + "/test.html")
log.Println("requesting http://127.0.0.1:" + cport + "/test.html")
if err != nil {
@ -30,40 +31,26 @@ func TestTCP(t *testing.T) {
}
log.Println(resp)
}
*/
func TestUDP(t *testing.T) {
go echo()
countdown(3)
countdown(11)
echoclient()
countdown(11)
go serveudp()
countdown(longcount)
countdown(61)
go clientudp()
countdown(longcount)
countdown(61)
setupudp()
conn, err := net.DialUDP("udp", udplocaladdr, ssulocaladdr)
if err != nil {
t.Fatal(err)
}
message := []byte("Hello SSU")
message := []byte("Hello UDP")
_, err = conn.Write(message)
if err != nil {
t.Fatal("SSU error", err)
t.Fatal("UDP error", err)
}
log.Println(string(message))
}
/*
func TestUDPeasy(t *testing.T) {
go echo()
time.Sleep(time.Duration(1 * time.Second))
conn, err := net.DialUDP("udp", udplocaladdr, udpserveraddr)
//defer conn.Close()
if err != nil {
t.Fatal(err)
}
_, err = conn.Write([]byte("Hello SSU"))
if err != nil {
t.Fatal("SSU error", err)
}
}
*/

View File

@ -1,391 +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 save the tunnel keys long-term
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 TCP Client 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
}
}
//SetClientLeaseSetKey sets
func SetClientLeaseSetKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetKey = s
return nil
}
}
//SetClientLeaseSetPrivateKey sets
func SetClientLeaseSetPrivateKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetPrivateKey = s
return nil
}
}
//SetClientLeaseSetPrivateSigningKey sets
func SetClientLeaseSetPrivateSigningKey(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.leaseSetPrivateSigningKey = s
return nil
}
}
//SetClientMessageReliability sets
func SetClientMessageReliability(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.messageReliability = s
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
}
}
//SetClientFastRecieve tells clients use the i2cp.fastRecieve option
func SetClientFastRecieve(b bool) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
if b {
c.fastRecieve = "true"
return nil
}
c.fastRecieve = "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 = "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 = "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 nil
}
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
}
}
//SetKeyFile sets
func SetClientPassword(s string) func(*SAMClientForwarder) error {
return func(c *SAMClientForwarder) error {
c.passfile = s
return nil
}
}

View File

@ -6,100 +6,72 @@ import (
"net"
//"os"
//"path/filepath"
"strconv"
"strings"
)
import (
"github.com/eyedeekay/sam-forwarder/config"
"github.com/eyedeekay/sam-forwarder/hashhash"
"github.com/eyedeekay/sam-forwarder/i2pkeys"
"github.com/eyedeekay/sam-forwarder/interface"
"github.com/eyedeekay/sam-forwarder/options"
"github.com/eyedeekay/sam3"
"github.com/eyedeekay/sam3/i2pkeys"
)
// SAMClientForwarder is a tcp proxy that automatically forwards ports to i2p
type SAMClientForwarder struct {
SamHost string
SamPort string
TunName string
Type string
TargetHost string
TargetPort string
samConn *sam3.SAM
SamKeys i2pkeys.I2PKeys
Hasher *hashhash.Hasher
connectStream *sam3.StreamSession
dest string
addr i2pkeys.I2PAddr
publishConnection net.Listener
Bytes map[string]int
ByteLimit int
FilePath string
file io.ReadWriter
save bool
file io.ReadWriter
up bool
// samcatd options
passfile string
// config
Conf *i2ptunconf.Conf
}
// I2CP options
encryptLeaseSet string
leaseSetKey string
leaseSetPrivateKey string
leaseSetPrivateSigningKey string
LeaseSetKeys *i2pkeys.I2PKeys
inAllowZeroHop string
outAllowZeroHop string
inLength string
outLength string
inQuantity string
outQuantity string
inVariance string
outVariance string
inBackupQuantity string
outBackupQuantity string
fastRecieve string
useCompression string
messageReliability string
closeIdle string
closeIdleTime string
reduceIdle string
reduceIdleTime string
reduceIdleQuantity string
func (f *SAMClientForwarder) Config() *i2ptunconf.Conf {
if f.Conf == nil {
f.Conf = i2ptunconf.NewI2PBlankTunConf()
}
return f.Conf
}
//Streaming Library options
accessListType string
accessList []string
func (f *SAMClientForwarder) GetType() string {
return f.Config().Type
}
func (f *SAMClientForwarder) ID() string {
return f.TunName
return f.Config().TunName
}
func (f *SAMClientForwarder) Keys() i2pkeys.I2PKeys {
return f.SamKeys
}
func (f *SAMClientForwarder) print() []string {
lsk, lspk, lspsk := f.leasesetsettings()
return []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.fastRecieve=" + f.fastRecieve,
"i2cp.gzip=" + f.useCompression,
"i2cp.reduceOnIdle=" + f.reduceIdle,
"i2cp.reduceIdleTime=" + f.reduceIdleTime,
"i2cp.reduceQuantity=" + f.reduceIdleQuantity,
"i2cp.closeOnIdle=" + f.closeIdle,
"i2cp.closeIdleTime=" + f.closeIdleTime,
"i2cp.messageReliability" + f.messageReliability,
"i2cp.encryptLeaseSet=" + f.encryptLeaseSet,
lsk, lspk, lspsk,
f.accesslisttype(),
f.accesslist(),
return f.Config().PrintSlice()
}
func (f *SAMClientForwarder) 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 *SAMClientForwarder) Cleanup() {
@ -110,12 +82,12 @@ func (f *SAMClientForwarder) Cleanup() {
func (f *SAMClientForwarder) Print() string {
var r string
r += "name=" + f.TunName + "\n"
r += "type=" + f.Type + "\n"
r += "name=" + f.Config().TunName + "\n"
r += "type=" + f.Config().Type + "\n"
r += "base32=" + f.Base32() + "\n"
r += "base64=" + f.Base64() + "\n"
r += "dest=" + f.dest + "\n"
r += "ntcpclient\n"
r += "dest=" + f.Config().ClientDest + "\n"
//r += "ntcpclient\n"
for _, s := range f.print() {
r += s + "\n"
}
@ -137,20 +109,20 @@ func (f *SAMClientForwarder) Search(search string) string {
}
func (f *SAMClientForwarder) accesslisttype() string {
if f.accessListType == "whitelist" {
if f.Config().AccessListType == "allowlist" {
return "i2cp.enableAccessList=true"
} else if f.accessListType == "blacklist" {
} else if f.Config().AccessListType == "blocklist" {
return "i2cp.enableBlackList=true"
} else if f.accessListType == "none" {
} else if f.Config().AccessListType == "none" {
return ""
}
return ""
}
func (f *SAMClientForwarder) accesslist() string {
if f.accessListType != "" && len(f.accessList) > 0 {
if f.Config().AccessListType != "" && len(f.Config().AccessList) > 0 {
r := ""
for _, s := range f.accessList {
for _, s := range f.Config().AccessList {
r += s + ","
}
return "i2cp.accessList=" + strings.TrimSuffix(r, ",")
@ -160,21 +132,21 @@ func (f *SAMClientForwarder) accesslist() string {
func (f *SAMClientForwarder) leasesetsettings() (string, string, string) {
var r, s, t string
if f.leaseSetKey != "" {
r = "i2cp.leaseSetKey=" + f.leaseSetKey
if f.Config().LeaseSetKey != "" {
r = "i2cp.leaseSetKey=" + f.Config().LeaseSetKey
}
if f.leaseSetPrivateKey != "" {
s = "i2cp.leaseSetPrivateKey=" + f.leaseSetPrivateKey
if f.Config().LeaseSetPrivateKey != "" {
s = "i2cp.leaseSetPrivateKey=" + f.Config().LeaseSetPrivateKey
}
if f.leaseSetPrivateSigningKey != "" {
t = "i2cp.leaseSetPrivateSigningKey=" + f.leaseSetPrivateSigningKey
if f.Config().LeaseSetPrivateSigningKey != "" {
t = "i2cp.leaseSetPrivateSigningKey=" + f.Config().LeaseSetPrivateSigningKey
}
return r, s, t
}
// 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
return f.Config().TargetHost + ":" + f.Config().TargetPort
}
// Destination returns the destination of the i2p service you want to forward locally
@ -183,7 +155,7 @@ func (f *SAMClientForwarder) Destination() string {
}
func (f *SAMClientForwarder) sam() string {
return f.SamHost + ":" + f.SamPort
return f.Config().SamHost + ":" + f.Config().SamPort
}
//Base32 returns the base32 address of the local destination
@ -191,6 +163,13 @@ func (f *SAMClientForwarder) Base32() string {
return f.SamKeys.Addr().Base32()
}
//Base32Readable returns the base32 address where the local service is being forwarded
func (f *SAMClientForwarder) Base32Readable() string {
b32 := strings.Replace(f.Base32(), ".b32.i2p", "", 1)
rhash, _ := f.Hasher.Friendly(b32)
return rhash + " " + strconv.Itoa(len(b32))
}
//Base64 returns the base64 address of the local destiantion
func (f *SAMClientForwarder) Base64() string {
return f.SamKeys.Addr().Base64()
@ -216,10 +195,10 @@ func (f *SAMClientForwarder) forward(conn net.Conn) {
//Serve starts the SAM connection and and forwards the local host:port to i2p
func (f *SAMClientForwarder) Serve() error {
if f.addr, err = f.samConn.Lookup(f.dest); err != nil {
if f.addr, err = f.samConn.Lookup(f.Config().ClientDest); err != nil {
return err
}
if f.connectStream, err = f.samConn.NewStreamSession(f.TunName, f.SamKeys, f.print()); err != nil {
if f.connectStream, err = f.samConn.NewStreamSession(f.Config().TunName, f.SamKeys, f.print()); err != nil {
log.Println("Stream Creation error:", err.Error())
return err
}
@ -231,84 +210,72 @@ func (f *SAMClientForwarder) Serve() error {
return err
}
log.Println("Forwarding client to i2p address:", f.addr.Base32())
log.Println("Human-readable hash of Client:\n ", f.Base32Readable())
go f.forward(conn)
}
}
func (f *SAMClientForwarder) Up() bool {
return f.up
}
//Close shuts the whole thing down.
func (f *SAMClientForwarder) Close() error {
var err error
err = f.samConn.Close()
f.up = false
err = f.connectStream.Close()
err = f.publishConnection.Close()
return err
}
//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 = "2"
s.outQuantity = "2"
s.inVariance = "1"
s.outVariance = "1"
s.inBackupQuantity = "3"
s.outBackupQuantity = "3"
s.inAllowZeroHop = "false"
s.outAllowZeroHop = "false"
s.encryptLeaseSet = "false"
s.leaseSetKey = ""
s.leaseSetPrivateKey = ""
s.leaseSetPrivateSigningKey = ""
s.fastRecieve = "false"
s.useCompression = "true"
s.reduceIdle = "false"
s.reduceIdleTime = "300000"
s.reduceIdleQuantity = "4"
s.closeIdle = "false"
s.closeIdleTime = "300000"
s.dest = "none"
s.Type = "client"
s.messageReliability = "none"
s.passfile = ""
s.dest = "i2p-projekt.i2p"
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 {
func (s *SAMClientForwarder) Load() (samtunnel.SAMTunnel, error) {
if s.publishConnection, err = net.Listen("tcp", s.Config().TargetHost+":"+s.Config().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.save {
if s.Config().SaveFile {
log.Println("Saving i2p keys")
}
if s.SamKeys, err = sfi2pkeys.Load(s.FilePath, s.TunName, s.passfile, s.samConn, s.save); err != nil {
if s.SamKeys, err = sfi2pkeys.Load(s.Config().FilePath, s.Config().TunName, s.Config().KeyFilePath, s.samConn, s.Config().SaveFile); err != nil {
return nil, err
}
log.Println("Destination keys generated, tunnel name:", s.TunName)
if s.save {
if err := sfi2pkeys.Save(s.FilePath, s.TunName, s.passfile, s.SamKeys); err != nil {
log.Println("Destination keys generated, tunnel name:", s.Config().TunName)
if s.Config().SaveFile {
if err := sfi2pkeys.Save(s.Config().FilePath, s.Config().TunName, s.Config().KeyFilePath, s.SamKeys); err != nil {
return nil, err
}
log.Println("Saved tunnel keys for", s.TunName)
log.Println("Saved tunnel keys for", s.Conf.TunName, "in", s.Conf.FilePath)
}
return &s, nil
s.Hasher, err = hashhash.NewHasher(len(strings.Replace(s.Base32(), ".b32.i2p", "", 1)))
if err != nil {
return nil, err
}
s.up = true
return s, nil
}
//NewSAMClientForwarder makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMClientForwarder(host, port string) (samtunnel.SAMTunnel, error) {
return NewSAMClientForwarderFromOptions(samoptions.SetHost(host), samoptions.SetPort(port))
}
//NewSAMClientForwarderFromOptions makes a new SAM forwarder with default options, accepts host:port arguments
func NewSAMClientForwarderFromOptions(opts ...func(samtunnel.SAMTunnel) error) (*SAMClientForwarder, error) {
var s SAMClientForwarder
s.Conf = i2ptunconf.NewI2PBlankTunConf()
s.Conf.Type = "tcpclient"
for _, o := range opts {
if err := o(&s); err != nil {
return nil, err
}
}
l, e := s.Load()
if e != nil {
return nil, e
}
return l.(*SAMClientForwarder), nil
}

View File

@ -1,412 +1,9 @@
package samforwarder
import (
"fmt"
"strconv"
)
//Option is a SAMForwarder Option
type Option func(*SAMForwarder) error
//SetFilePath sets the path to save the config file at.
func SetFilePath(s string) func(*SAMForwarder) error {
//SetByteLimit sets the number of hops inbound
func SetByteLimit(u int64) 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 {
c.Type = "server"
return nil
}
}
}
//SetSaveFile tells the router to save the tunnel's keys long-term
func SetSaveFile(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.save = b
return nil
}
}
//SetHost sets the host of the service to forward
func SetHost(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.TargetHost = s
return nil
}
}
//SetPort sets the port of the service to forward
func SetPort(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) 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.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
}
}
//SetLeaseSetKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetKey = s
return nil
}
}
//SetLeaseSetPrivateKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetPrivateKey = s
return nil
}
}
//SetLeaseSetPrivateSigningKey sets the host of the SAMForwarder's SAM bridge
func SetLeaseSetPrivateSigningKey(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.leaseSetPrivateSigningKey = s
return nil
}
}
//SetMessageReliability sets the host of the SAMForwarder's SAM bridge
func SetMessageReliability(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.messageReliability = s
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
}
}
//SetFastRecieve tells clients to use compression
func SetFastRecieve(b bool) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
if b {
c.fastRecieve = "true"
return nil
}
c.fastRecieve = "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 = "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 = "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 = "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 = "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 nil
}
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")
}
}
*/
//SetKeyFile sets
func SetKeyFile(s string) func(*SAMForwarder) error {
return func(c *SAMForwarder) error {
c.passfile = s
c.ByteLimit = u
return nil
}
}

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