2 Commits

Author SHA1 Message Date
idk
c1ee187137 Merge branch 'master' of github.com:eyedeekay/i2p-tools-1 into docker 2020-05-06 20:30:44 -04:00
idk
da30f0cb31 Trigger build 2020-05-06 20:29:46 -04:00
31 changed files with 508 additions and 1976 deletions

View File

@@ -1,8 +0,0 @@
.idea
.git
.gitlab-ci.yml
.vscode
# CI cache folder storing docker images
ci-exports

8
.gitignore vendored
View File

@@ -5,11 +5,3 @@
i2pseeds.su3 i2pseeds.su3
*.pem *.pem
onion.key onion.key
tmp/
i2p-tools-*
*.crl
*.crt
*.pem
plugin
reseed-tools*
data-dir*

View File

@@ -1,106 +0,0 @@
image: docker:19.03.12
stages:
- docker_test
- docker_push
variables:
# When using dind service, we need to instruct docker to talk with
# the daemon started inside of the service. The daemon is available
# with a network connection instead of the default
# /var/run/docker.sock socket. Docker 19.03 does this automatically
# by setting the DOCKER_HOST in
# https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29
#
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
#
# Specify to Docker where to create the certificates, Docker will
# create them automatically on boot, and will create
# `/certs/client` that will be shared between the service and job
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
services:
- docker:19.03.12-dind
.docker_cache:
cache:
# The same key should be used across branches
key: "$CI_COMMIT_REF_SLUG"
paths:
- ci-exports/*.tar
# Make sure we can build a docker image
# It's cached for later jobs
build_docker:
extends:
- .docker_cache
stage: docker_test
script:
# Try to load latest branch image from local tar or from registry
- docker load ci-exports/$CI_COMMIT_REF_SLUG.tar || docker pull $CI_REGISTRY_IMAGE:latest || true
- docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
- mkdir -p ci-exports/
- docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
# Publishes the configured CI registry (by default that's gitlab's registry)
push_ci_registry:
extends:
- .docker_cache
stage: docker_push
cache:
policy: pull
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- cat ci-exports/$CI_COMMIT_REF_SLUG.tar | docker load
- docker tag $CI_REGISTRY_IMAGE:latest $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker push $CI_REGISTRY_IMAGE:latest
only:
refs:
# Make sure to protect these tags!
- /^v(\d+\.){2,3}\d+$/
- /.+-release$/
variables:
- $CI_REGISTRY
- $CI_REGISTRY_USER
- $CI_REGISTRY_PASSWORD
- $CI_REGISTRY_IMAGE
# Publishes the cached image to docker
push_dockerhub_registry:
extends:
- .docker_cache
stage: docker_push
cache:
policy: pull
before_script:
- docker login -u $DOCKERHUB_REGISTRY_USER -p $DOCKERHUB_REGISTRY_PASSWORD $DOCKERHUB_REGISTRY
script:
- cat ci-exports/$CI_COMMIT_REF_SLUG.tar | docker load
- docker tag $CI_REGISTRY_IMAGE:latest $DOCKERHUB_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker tag $CI_REGISTRY_IMAGE:latest $DOCKERHUB_REGISTRY_IMAGE:latest
- docker push $DOCKERHUB_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker push $DOCKERHUB_REGISTRY_IMAGE:latest
# Push the readme to dockerhub
- >-
docker run -v $PWD:/workspace
-e DOCKERHUB_USERNAME="$DOCKERHUB_REGISTRY_USER"
-e DOCKERHUB_PASSWORD="$DOCKERHUB_REGISTRY_PASSWORD"
-e DOCKERHUB_REPOSITORY="$DOCKERHUB_REGISTRY_IMAGE"
-e README_FILEPATH='/workspace/README.md'
peterevans/dockerhub-description:2
only:
refs:
# Make sure to protect these tags!
- /^v(\d+\.){2,3}\d+$/
- /.+-release$/
variables:
- $DOCKERHUB_REGISTRY
- $DOCKERHUB_REGISTRY_USER
- $DOCKERHUB_REGISTRY_PASSWORD
- $DOCKERHUB_REGISTRY_IMAGE

View File

@@ -31,4 +31,4 @@
* numRi per su3 file: 75 --> 77 * numRi per su3 file: 75 --> 77
2016-01 2016-01
* fork from https://i2pgit.org/idk/reseed-tools * fork from https://github.com/MDrollette/i2p-tools

View File

@@ -1,14 +1,14 @@
FROM debian:stable-backports FROM debian:stable-backports
ARG I2P_GID=1000 ARG I2P_GID=1000
ARG I2P_UID=1000 ARG I2P_UID=1000
COPY . /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools COPY . /var/lib/i2p/go/src/github.com/eyedeekay/i2p-tools-1
WORKDIR /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools WORKDIR /var/lib/i2p/go/src/github.com/eyedeekay/i2p-tools-1
RUN apt-get update && \ RUN apt-get update && \
apt-get dist-upgrade -y && \ apt-get dist-upgrade -y && \
apt-get install -y git golang-go make && \ apt-get install -y git golang-1.13-go make && \
mkdir -p /var/lib/i2p/i2p-config/reseed && \ mkdir -p /var/lib/i2p/i2p-config/reseed && \
chown -R $I2P_UID:$I2P_GID /var/lib/i2p && chmod -R o+rwx /var/lib/i2p chown -R $I2P_UID:$I2P_GID /var/lib/i2p && chmod -R o+rwx /var/lib/i2p
RUN go build -v -tags netgo -ldflags '-w -extldflags "-static"' RUN /usr/lib/go-1.13/bin/go build -v -tags netgo -ldflags '-w -extldflags "-static"'
USER $I2P_UID USER $I2P_UID
WORKDIR /var/lib/i2p/i2p-config/reseed WORKDIR /var/lib/i2p/i2p-config/reseed
ENTRYPOINT [ "/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/entrypoint.sh" ] ENTRYPOINT [ "/var/lib/i2p/go/src/github.com/eyedeekay/i2p-tools-1/i2p-tools-1", "reseed", "--yes=true", "--netdb=/var/lib/i2p/i2p-config/netDb" ]

206
Makefile
View File

@@ -1,6 +1,6 @@
VERSION=0.2.0 VERSION=0.0.3
APP=reseed-tools APP=i2p-tools-1
USER_GH=eyedeekay USER_GH=eyedeekay
GOOS?=$(shell uname -s | tr A-Z a-z) GOOS?=$(shell uname -s | tr A-Z a-z)
@@ -8,74 +8,64 @@ GOARCH?="amd64"
ARG=-v -tags netgo -ldflags '-w -extldflags "-static"' ARG=-v -tags netgo -ldflags '-w -extldflags "-static"'
#MIN_GO_VERSION=`ls /usr/lib/go-1.14 2>/dev/null >/dev/null && echo 1.14` MIN_GO_VERSION=`ls /usr/lib/go-1.14 2>/dev/null >/dev/null && echo 1.14`
MIN_GO_VERSION?=1.15 MIN_GO_VERSION?=1.13
I2P_UID=$(shell id -u i2psvc) I2P_UID=$(shell id -u i2psvc)
I2P_GID=$(shell id -g i2psvc) I2P_GID=$(shell id -g i2psvc)
WHOAMI=$(shell whoami)
echo: echo:
@echo "type make version to do release $(APP) $(VERSION) $(GOOS) $(GOARCH) $(MIN_GO_VERSION) $(I2P_UID) $(I2P_GID)" @echo "type make version to do release $(APP) $(VERSION) $(GOOS) $(GOARCH) $(MIN_GO_VERSION) $(I2P_UID) $(I2P_GID)"
build: version:
go build $(ARG) -o reseed-tools-$(GOOS)-$(GOARCH) cat README.md | gothub release -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -
1.15-build: gofmt edit:
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build $(ARG) -o reseed-tools-$(GOOS)-$(GOARCH) cat README.md | gothub edit -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -
upload: binary tar
gothub upload -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f ../i2p-tools.tar.xz -n "i2p-tools.tar.xz"
build: gofmt
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build $(ARG) -o i2p-tools-$(GOOS)-$(GOARCH)
clean: clean:
rm reseed-tools-* *.key *.i2pKeys *.crt *.crl *.pem tmp -rfv rm i2p-tools-* *.key *.i2pKeys *.crt *.crl *.pem tmp -rf
binary:
GOOS=darwin GOARCH=amd64 make build
GOOS=linux GOARCH=386 make build
GOOS=linux GOARCH=amd64 make build
GOOS=linux GOARCH=arm make build
GOOS=linux GOARCH=arm64 make build
GOOS=openbsd GOARCH=amd64 make build
GOOS=freebsd GOARCH=386 make build
GOOS=freebsd GOARCH=amd64 make build
tar: tar:
tar --exclude="./.git" --exclude="./tmp" -cvf ../reseed-tools.tar.xz . tar --exclude="./.git" --exclude="./tmp" -cvf ../i2p-tools.tar.xz .
install: install:
install -m755 reseed-tools-$(GOOS)-$(GOARCH) /usr/bin/reseed-tools install -m755 i2p-tools-$(GOOS)-$(GOARCH) /usr/local/bin/i2p-tools
install -m644 etc/default/reseed /etc/default/reseed
install -m755 etc/init.d/reseed /etc/init.d/reseed install -m755 etc/init.d/reseed /etc/init.d/reseed
mkdir -p /etc/systemd/system/reseed.d/
mkdir -p /var/lib/i2p
install -g i2psvc -o i2psvc -d /var/lib/i2p/i2p-config/reseed/
install -m644 etc/systemd/system/reseed.d/reseed.conf /etc/systemd/system/reseed.d/reseed.conf
install -m644 etc/systemd/system/reseed.d/reseed.service /etc/systemd/system/reseed.d/reseed.service
checkinstall: build
fakeroot checkinstall \
--default \
--install=no \
--fstrans=yes \
--pkgname=reseed-tools \
--pkgversion=$(VERSION) \
--pkggroup=net \
--pkgrelease=1 \
--pkgsource="https://i2pgit.org/idk/reseed-tools" \
--maintainer="$(SIGNER)" \
--requires="i2p,i2p-router" \
--suggests="i2p,i2p-router,syndie,tor,tsocks" \
--nodoc \
--deldoc=yes \
--deldesc=yes \
--backup=no
### You shouldn't need to use these now that the go mod require rule is fixed, ### You shouldn't need to use these now that the go mod require rule is fixed,
## but I'm leaving them in here because it made it easier to test that both ## but I'm leaving them in here because it made it easier to test that both
## versions behaved the same way. -idk ## versions behaved the same way. -idk
build-fork: build-fork:
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o reseed-tools-idk /usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o i2p-tools-idk
build-unfork: build-unfork:
/usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o reseed-tools-md /usr/lib/go-$(MIN_GO_VERSION)/bin/go build -o i2p-tools-md
fork: fork:
sed -i 's|idk/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go sed -i 's|MDrollette/i2p-tools|eyedeekay/i2p-tools-1|g' main.go cmd/*.go reseed/*.go su3/*.go
make gofmt build-fork make gofmt build-fork
unfork: unfork:
sed -i 's|idk/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go sed -i 's|eyedeekay/i2p-tools-1|MDrollette/i2p-tools|g' main.go cmd/*.go reseed/*.go su3/*.go
sed -i 's|RTradeLtd/reseed-tools|idk/reseed-tools|g' main.go cmd/*.go reseed/*.go su3/*.go sed -i 's|RTradeLtd/i2p-tools-1|MDrollette/i2p-tools|g' main.go cmd/*.go reseed/*.go su3/*.go
make gofmt build-unfork make gofmt build-unfork
gofmt: gofmt:
@@ -84,12 +74,12 @@ gofmt:
try: try:
mkdir -p tmp && \ mkdir -p tmp && \
cd tmp && \ cd tmp && \
../reseed-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p --littleboss=start ../i2p-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p --littleboss=start
stop: stop:
mkdir -p tmp && \ mkdir -p tmp && \
cd tmp && \ cd tmp && \
../reseed-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p --littleboss=stop ../i2p-tools-$(GOOS)-$(GOARCH) reseed --signer=you@mail.i2p --netdb=/home/idk/.i2p/netDb --tlsHost=your-domain.tld --onion --p2p --i2p --littleboss=stop
docker: docker:
docker build -t eyedeekay/reseed . docker build -t eyedeekay/reseed .
@@ -117,140 +107,18 @@ docker-server:
--publish 8443:8443 \ --publish 8443:8443 \
--restart=always \ --restart=always \
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \ --volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \ --volume /var/lib/i2p/i2p-config/reseed-keys:/var/lib/i2p/i2p-config/reseed \
eyedeekay/reseed \ eyedeekay/reseed \
--signer=hankhill19580@gmail.com --signer=hankhill19580@gmail.com
docker logs -f reseed docker logs -f reseed
docker-run: docker-run:
docker run -itd \ docker run --rm -itd \
--name reseed \ --name reseed \
--user $(I2P_UID) \ --user $(I2P_UID) \
--group-add $(I2P_GID) \ --group-add $(I2P_GID) \
--publish 8443:8443 \ --publish 8443:8443 \
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \ --volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \ --volume /var/lib/i2p/i2p-config/reseed-keys:/var/lib/i2p/i2p-config/reseed \
eyedeekay/reseed \ eyedeekay/reseed \
--signer=hankhill19580@gmail.com --signer=hankhill19580@gmail.com
docker-homerun:
docker run -itd \
--name reseed \
--user 1000 \
--group-add 1000 \
--publish 8443:8443 \
--volume $(HOME)/i2p/netDb:/var/lib/i2p/i2p-config/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed:z \
eyedeekay/reseed \
--signer=hankhill19580@gmail.com
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/
export CGO_CFLAGS=-I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/
gojava:
go get -u -v github.com/sridharv/gojava
cp -v ~/go/bin/gojava ./gojava
jar: gojava
echo $(JAVA_HOME)
./gojava -v -o reseed.jar -s . build ./reseed
release: version upload checkinstall upload-single-deb binary upload-bin plguins upload-plugins
version:
cat README.md | gothub release -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -
edit:
cat README.md | gothub edit -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -d -
upload: tar
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f ../reseed-tools.tar.xz -n "reseed-tools.tar.xz"
binary:
GOOS=darwin GOARCH=amd64 make build
GOOS=darwin GOARCH=arm64 make build
GOOS=linux GOARCH=386 make build
GOOS=linux GOARCH=amd64 make build
GOOS=linux GOARCH=arm make build
GOOS=linux GOARCH=arm64 make build
GOOS=openbsd GOARCH=amd64 make build
GOOS=freebsd GOARCH=386 make build
GOOS=freebsd GOARCH=amd64 make build
GOOS=windows GOARCH=amd64 make build
GOOS=windows GOARCH=386 make build
plugins: binary
GOOS=darwin GOARCH=amd64 make su3s
GOOS=darwin GOARCH=arm64 make su3s
GOOS=linux GOARCH=386 make su3s
GOOS=linux GOARCH=amd64 make su3s
GOOS=linux GOARCH=arm make su3s
GOOS=linux GOARCH=arm64 make su3s
GOOS=openbsd GOARCH=amd64 make su3s
GOOS=freebsd GOARCH=386 make su3s
GOOS=freebsd GOARCH=amd64 make su3s
GOOS=windows GOARCH=amd64 make su3s
GOOS=windows GOARCH=386 make su3s
upload-bin:
GOOS=darwin GOARCH=amd64 make upload-single-bin
GOOS=darwin GOARCH=arm64 make upload-single-bin
GOOS=linux GOARCH=386 make upload-single-bin
GOOS=linux GOARCH=amd64 make upload-single-bin
GOOS=linux GOARCH=arm make upload-single-bin
GOOS=linux GOARCH=arm64 make upload-single-bin
GOOS=openbsd GOARCH=amd64 make upload-single-bin
GOOS=freebsd GOARCH=386 make upload-single-bin
GOOS=freebsd GOARCH=amd64 make upload-single-bin
GOOS=windows GOARCH=amd64 make upload-single-bin
GOOS=windows GOARCH=386 make upload-single-bin
upload-su3s:
GOOS=darwin GOARCH=amd64 make upload-single-su3
GOOS=darwin GOARCH=arm64 make upload-single-su3
GOOS=linux GOARCH=386 make upload-single-su3
GOOS=linux GOARCH=amd64 make upload-single-su3
GOOS=linux GOARCH=arm make upload-single-su3
GOOS=linux GOARCH=arm64 make upload-single-su3
GOOS=openbsd GOARCH=amd64 make upload-single-su3
GOOS=freebsd GOARCH=386 make upload-single-su3
GOOS=freebsd GOARCH=amd64 make upload-single-su3
GOOS=windows GOARCH=amd64 make upload-single-su3
GOOS=windows GOARCH=386 make upload-single-su3
upload-single-deb:
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools_$(VERSION)-1_amd64.deb -l "`sha256sum reseed-tools_$(VERSION)-1_amd64.deb`" -n "reseed-tools_$(VERSION)-1_amd64.deb"
upload-single-bin:
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools-"$(GOOS)"-"$(GOARCH)" -l "`sha256sum reseed-tools-$(GOOS)-$(GOARCH)`" -n "reseed-tools-$(GOOS)"-"$(GOARCH)"
upload-single-su3:
gothub upload -R -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(APP) -t v$(VERSION) -f reseed-tools-"$(GOOS)"-"$(GOARCH).su3" -l "`sha256sum reseed-tools-$(GOOS)-$(GOARCH).su3`" -n "reseed-tools-$(GOOS)"-"$(GOARCH).su3"
tmp/content:
mkdir -p tmp
cp -rv content tmp/content
su3s: tmp/content
i2p.plugin.native -name=reseed-tools-$(GOOS)-$(GOARCH) \
-signer=hankhill19580@gmail.com \
-version "$(VERSION)" \
-author=hankhill19580@gmail.com \
-autostart=true \
-clientname=reseed-tools-$(GOOS)-$(GOARCH) \
-command="reseed-tools-$(GOOS)-$(GOARCH) reseed --yes --signer=you@mail.i2p --netdb=\$$CONFIG/netDb" \
-consolename="Reseed Tools" \
-consoleurl="http://127.0.0.1:8443" \
-updateurl="http://idk.i2p/reseed-tools/reseed-tools-$(GOOS)-$(GOARCH).su3" \
-website="http://idk.i2p/reseed-tools/" \
-icondata="content/images/reseed.png" \
-delaystart="3" \
-desc="`cat description-pak`" \
-exename=reseed-tools-$(GOOS)-$(GOARCH) \
-targetos="$(GOOS)" \
-res=tmp/ \
-license=MIT
unzip -o reseed-tools-$(GOOS)-$(GOARCH).zip -d reseed-tools-$(GOOS)-$(GOARCH)-zip
#export sumbblinux=`sha256sum "../reseed-tools-linux.su3"`
#export sumbbwindows=`sha256sum "../reseed-tools-windows.su3"`

227
README.md
View File

@@ -1,142 +1,20 @@
I2P Reseed Tools I2P Reseed Tools
================== ==================
This tool provides a secure and efficient reseed server for the I2P network. There are several utility commands to This tool provides a secure and efficient reseed server for the I2P network. There are several utility commands to create, sign, and validate SU3 files.
create, sign, and validate SU3 files. Please note that this requires at least Go version 1.13, and uses Go Modules.
## Dependencies ## Installation
`go`, `git`, and optionally `make` are required to build the project. If you have go installed you can download, build, and install this tool with `go get`
Precompiled binaries for most platforms are available at my github mirror
https://github.com/eyedeekay/i2p-tools-1.
In order to install the build-dependencies on Ubuntu or Debian, you may use:
```sh
sudo apt-get install golang-go git make
```
## Installation(From Source)
``` ```
git clone https://i2pgit.org/idk/reseed-tools go get github.com/MDrollette/i2p-tools
cd reseed-tools i2p-tools -h
make build
# Optionally, if you want to install to /usr/bin/reseed-tools
sudo make install
``` ```
## Usage ## Usage
#### Debian/Ubuntu note: ### Docker!
Debian users who are running I2P as a system service must also run the
`reseed-tools` as the same user. This is so that the reseed-tools can access
the I2P service's netDb directory. On Debian and Ubuntu, that user is `i2psvc`
and the netDb directory is: `/var/lib/i2p/i2p-config/netDb`.
##### Systemd Service
A systemd service is provided which should work with the I2P Debian package
when reseed-tools is installed in `/usr/bin/reseed-tools`. If you install with
`make install` this service is also installed. This service will cause the
bundles to regenerate every 12 hours.
The contact email for your reseed should be added in:
`/etc/systemd/system/reseed.d/reseed.conf`.
Self-signed certificates will be auto-generated for these services. To change
this you should edit the `/etc/systemd/system/reseed.d/reseed.service`.
- To enable starting the reseed service automatically with the system: `sudo systemctl enable reseed.service`
- To run the service manually: `sudo sysctl start reseed.service`
- To reload the systemd services: `sudo systemctl daemon-reload`
- To view the status/logs: `sudo journalctl -u reseed.service`
##### SysV Service
An initscript is also provided. The initscript, unlike the systemd service,
cannot schedule itself to restart. You should restart the service roughly once
a day to ensure that the information does not expire.
The contact email for your reseed should be added in:
`/etc/init.d/reseed`.
Self-signed certificates will be auto-generated for these services. To change
this you should edit the `/etc/init.d/reseed`.
### Without a webserver, standalone with TLS support
If this is your first time running a reseed server (ie. you don't have any existing keys),
you can simply run the command and follow the prompts to create the appropriate keys, crl and certificates.
Afterwards an HTTPS reseed server will start on the default port and generate 6 files in your current directory
(a TLS key, certificate and crl, and a su3-file signing key, certificate and crl).
```
reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
```
## Example Commands:
### Locally behind a webserver (reverse proxy setup), preferred:
If you are using a reverse proxy server it may provide the TLS certificate instead.
```
reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
```
### Without a webserver, standalone, self-supervising(Automatic restarts)
```
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --littleboss=start
```
### Without a webserver, standalone, automatic OnionV3 with TLS support
```
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
```
### Without a webserver, standalone, serve P2P with LibP2P
```
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
```
### Without a webserver, standalone, upload a single signed .su3 to github
* This one isn't working yet, I'll get to it eventually, I've got a cooler idea now.
```
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=reseed-tools --ghuser=eyedeekay
```
### Without a webserver, standalone, in-network reseed
```
./reseed-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS
```
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, and LibP2P
```
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, I2P In-Network reseed, and LibP2P, self-supervising
```
./reseed-tools reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --littleboss=start
```
### Docker
To make it easier to deploy reseeds, it is possible to run this software as a To make it easier to deploy reseeds, it is possible to run this software as a
Docker image. Because the software requires access to a network database to host Docker image. Because the software requires access to a network database to host
@@ -146,8 +24,8 @@ and group inside the container as I2P.
When you run a reseed under Docker in this fashion, it will automatically When you run a reseed under Docker in this fashion, it will automatically
generate a self-signed certificate for your reseed server in a Docker volume generate a self-signed certificate for your reseed server in a Docker volume
mamed reseed-keys. *Back up this directory*, if it is lost it is impossible under your I2P directory. *Back up this directory*, if it is lost it is
to reproduce. impossible to reproduce.
Please note that Docker is not currently compatible with .onion reseeds unless Please note that Docker is not currently compatible with .onion reseeds unless
you pass the --network=host tag. you pass the --network=host tag.
@@ -159,7 +37,7 @@ you pass the --network=host tag.
--publish 443:8443 \ --publish 443:8443 \
--restart always \ --restart always \
--volume $HOME/.i2p/netDb:$HOME/.i2p/netDb:z \ --volume $HOME/.i2p/netDb:$HOME/.i2p/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \ --volume $HOME/i2p/reseed-keys:/var/lib/i2p/i2p-config/reseed \
eyedeekay/reseed \ eyedeekay/reseed \
--signer $YOUR_EMAIL_HERE --signer $YOUR_EMAIL_HERE
@@ -172,7 +50,7 @@ you pass the --network=host tag.
--publish 443:8443 \ --publish 443:8443 \
--restart always \ --restart always \
--volume /PATH/TO/USER/I2P/HERE/netDb:/var/lib/i2p/i2p-config/netDb:z \ --volume /PATH/TO/USER/I2P/HERE/netDb:/var/lib/i2p/i2p-config/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \ --volume /PATH/TO/USER/I2P/HERE/reseed-keys:/var/lib/i2p/i2p-config/reseed \
eyedeekay/reseed \ eyedeekay/reseed \
--signer $YOUR_EMAIL_HERE --signer $YOUR_EMAIL_HERE
@@ -190,6 +68,89 @@ work for you. In that case, just copy-and-paste:
--publish 443:8443 \ --publish 443:8443 \
--restart always \ --restart always \
--volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \ --volume /var/lib/i2p/i2p-config/netDb:/var/lib/i2p/i2p-config/netDb:z \
--volume reseed-keys:/var/lib/i2p/i2p-config/reseed \ --volume /var/lib/i2p/i2p-config/reseed-keys:/var/lib/i2p/i2p-config/reseed \
eyedeekay/reseed \ eyedeekay/reseed \
--signer $YOUR_EMAIL_HERE --signer $YOUR_EMAIL_HERE
### Locally behind a webserver (reverse proxy setup), preferred:
```
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --port=8443 --ip=127.0.0.1 --trustProxy
```
### Without a webserver, standalone with TLS support
```
i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld
```
If this is your first time running a reseed server (ie. you don't have any existing keys),
you can simply run the command and follow the prompts to create the appropriate keys, crl and certificates.
Afterwards an HTTPS reseed server will start on the default port and generate 6 files in your current directory
(a TLS key, certificate and crl, and a su3-file signing key, certificate and crl).
Get the source code here on github or a pre-build binary anonymously on
http://reseed.i2p/
http://j7xszhsjy7orrnbdys7yykrssv5imkn4eid7n5ikcnxuhpaaw6cq.b32.i2p/
also a short guide and complete tech info.
## Experimental, currently only available from eyedeekay/i2p-tools-1 fork
Requires ```go mod``` and at least go 1.13. To build the eyedeekay/i2p-tools-1
fork, from anywhere:
git clone https://github.com/eyedeekay/i2p-tools-1
cd i2p-tools-1
make build
### Without a webserver, standalone, self-supervising(Automatic restarts)
```
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --restart=start
```
### Without a webserver, standalone, automatic OnionV3 with TLS support
```
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --i2p --p2p
```
### Without a webserver, standalone, serve P2P with LibP2P
```
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --p2p
```
### Without a webserver, standalone, upload a single signed .su3 to github
* This one isn't working yet, look for it by ~Monday.
```
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --github --ghrepo=i2p-tools-1 --ghuser=eyedeekay
```
### Without a webserver, standalone, in-network reseed
```
./i2p-tools-1 reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --i2p
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS
```
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, and LibP2P
```
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p
```
### Without a webserver, standalone, Regular TLS, OnionV3 with TLS, I2P In-Network reseed, and LibP2P, self-supervising
```
./i2p-tools-1 reseed --tlsHost=your-domain.tld --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion --p2p --restart=start
```

View File

@@ -3,7 +3,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/urfave/cli" "github.com/codegangsta/cli"
) )
func NewKeygenCommand() cli.Command { func NewKeygenCommand() cli.Command {

View File

@@ -12,6 +12,9 @@ import (
"strconv" "strconv"
"time" "time"
//"crawshaw.io/littleboss"
"github.com/MDrollette/i2p-tools/reseed"
"github.com/codegangsta/cli"
"github.com/cretz/bine/tor" "github.com/cretz/bine/tor"
"github.com/cretz/bine/torutil" "github.com/cretz/bine/torutil"
"github.com/cretz/bine/torutil/ed25519" "github.com/cretz/bine/torutil/ed25519"
@@ -19,37 +22,9 @@ import (
"github.com/eyedeekay/sam3/i2pkeys" "github.com/eyedeekay/sam3/i2pkeys"
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/urfave/cli"
"i2pgit.org/idk/reseed-tools/reseed"
"github.com/eyedeekay/checki2cp/getmeanetdb"
) )
func getDefaultSigner() string {
intentionalsigner := os.Getenv("RESEED_EMAIL")
if intentionalsigner == "" {
adminsigner := os.Getenv("MAILTO")
if adminsigner != "" {
return adminsigner
}
return ""
}
return intentionalsigner
}
func getHostName() string {
hostname := os.Getenv("RESEED_HOSTNAME")
if hostname == "" {
hostname, _ = os.Hostname()
}
return hostname
}
func NewReseedCommand() cli.Command { func NewReseedCommand() cli.Command {
ndb, err := getmeanetdb.WhereIstheNetDB()
if err != nil {
log.Fatal(err)
}
return cli.Command{ return cli.Command{
Name: "reseed", Name: "reseed",
Usage: "Start a reseed server", Usage: "Start a reseed server",
@@ -57,12 +32,10 @@ func NewReseedCommand() cli.Command {
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "signer", Name: "signer",
Value: getDefaultSigner(),
Usage: "Your su3 signing ID (ex. something@mail.i2p)", Usage: "Your su3 signing ID (ex. something@mail.i2p)",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "tlsHost", Name: "tlsHost",
Value: getHostName(),
Usage: "The public hostname used on your TLS certificate", Usage: "The public hostname used on your TLS certificate",
}, },
cli.BoolFlag{ cli.BoolFlag{
@@ -84,7 +57,6 @@ func NewReseedCommand() cli.Command {
}, },
cli.StringFlag{ cli.StringFlag{
Name: "netdb", Name: "netdb",
Value: ndb,
Usage: "Path to NetDB directory containing routerInfos", Usage: "Path to NetDB directory containing routerInfos",
}, },
cli.StringFlag{ cli.StringFlag{
@@ -112,7 +84,7 @@ func NewReseedCommand() cli.Command {
}, },
cli.IntFlag{ cli.IntFlag{
Name: "numSu3", Name: "numSu3",
Value: 50, Value: 0,
Usage: "Number of su3 files to build (0 = automatic based on size of netdb)", Usage: "Number of su3 files to build (0 = automatic based on size of netdb)",
}, },
cli.StringFlag{ cli.StringFlag{
@@ -156,14 +128,10 @@ func NewReseedCommand() cli.Command {
Value: "127.0.0.1:7656", Value: "127.0.0.1:7656",
Usage: "Use this SAM address to set up I2P connections for in-network reseed", Usage: "Use this SAM address to set up I2P connections for in-network reseed",
}, },
cli.BoolFlag{
Name: "acme",
Usage: "Automatically generate a TLS certificate with the ACME protocol, defaults to Let's Encrypt",
},
cli.StringFlag{ cli.StringFlag{
Name: "acmeserver", Name: "littleboss",
Value: "https://acme-staging-v02.api.letsencrypt.org/directory", Value: "start",
Usage: "Use this server to issue a certificate with the ACME protocol", Usage: "Self-Supervise this application",
}, },
}, },
} }
@@ -215,6 +183,11 @@ func LoadKeys(keysPath string, c *cli.Context) (i2pkeys.I2PKeys, error) {
} }
func reseedAction(c *cli.Context) { func reseedAction(c *cli.Context) {
// validate flags
if c.String("littleboss") != "start" {
log.Println("--littleboss", c.String("littleboss"))
return
}
netdbDir := c.String("netdb") netdbDir := c.String("netdb")
if netdbDir == "" { if netdbDir == "" {
fmt.Println("--netdb is required") fmt.Println("--netdb is required")
@@ -235,53 +208,13 @@ func reseedAction(c *cli.Context) {
var i2pTlsCert, i2pTlsKey string var i2pTlsCert, i2pTlsKey string
var i2pkey i2pkeys.I2PKeys var i2pkey i2pkeys.I2PKeys
if tlsHost != "" {
onionTlsHost = tlsHost
i2pTlsHost = tlsHost
tlsKey = c.String("tlsKey")
// if no key is specified, default to the host.pem in the current dir
if tlsKey == "" {
tlsKey = tlsHost + ".pem"
onionTlsKey = tlsHost + ".pem"
i2pTlsKey = tlsHost + ".pem"
}
tlsCert = c.String("tlsCert")
// if no certificate is specified, default to the host.crt in the current dir
if tlsCert == "" {
tlsCert = tlsHost + ".crt"
onionTlsCert = tlsHost + ".crt"
i2pTlsCert = tlsHost + ".crt"
}
// prompt to create tls keys if they don't exist?
auto := c.Bool("yes")
// use ACME?
acme := c.Bool("acme")
if acme {
acmeserver := c.String("acmeserver")
err := checkUseAcmeCert(tlsHost, signerID, acmeserver, &tlsCert, &tlsKey, auto)
if nil != err {
log.Fatalln(err)
}
} else {
err := checkOrNewTLSCert(tlsHost, &tlsCert, &tlsKey, auto)
if nil != err {
log.Fatalln(err)
}
}
}
if c.Bool("i2p") { if c.Bool("i2p") {
var err error var err error
i2pkey, err = LoadKeys("reseed.i2pkeys", c) i2pkey, err = LoadKeys("reseed.i2pkeys", c)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
if i2pTlsHost == "" { i2pTlsHost = i2pkey.Addr().Base32()
i2pTlsHost = i2pkey.Addr().Base32()
}
if i2pTlsHost != "" { if i2pTlsHost != "" {
// if no key is specified, default to the host.pem in the current dir // if no key is specified, default to the host.pem in the current dir
if i2pTlsKey == "" { if i2pTlsKey == "" {
@@ -294,7 +227,7 @@ func reseedAction(c *cli.Context) {
} }
// prompt to create tls keys if they don't exist? // prompt to create tls keys if they don't exist?
auto := c.Bool("yes") auto := c.Bool("yes")
err := checkOrNewTLSCert(i2pTlsHost, &i2pTlsCert, &i2pTlsKey, auto) err := checkOrNewTLSCert(i2pTlsHost, &i2pTlsCert, &i2pTlsKey, auto)
if nil != err { if nil != err {
log.Fatalln(err) log.Fatalln(err)
@@ -317,9 +250,7 @@ func reseedAction(c *cli.Context) {
} }
ok = []byte(key.PrivateKey()) ok = []byte(key.PrivateKey())
} }
if onionTlsHost == "" { onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
onionTlsHost = torutil.OnionServiceIDFromPrivateKey(ed25519.PrivateKey(ok)) + ".onion"
}
err = ioutil.WriteFile(c.String("onionKey"), ok, 0644) err = ioutil.WriteFile(c.String("onionKey"), ok, 0644)
if err != nil { if err != nil {
log.Fatalln(err.Error()) log.Fatalln(err.Error())
@@ -336,7 +267,7 @@ func reseedAction(c *cli.Context) {
} }
// prompt to create tls keys if they don't exist? // prompt to create tls keys if they don't exist?
auto := c.Bool("yes") auto := c.Bool("yes")
err := checkOrNewTLSCert(onionTlsHost, &onionTlsCert, &onionTlsKey, auto) err := checkOrNewTLSCert(onionTlsHost, &onionTlsCert, &onionTlsKey, auto)
if nil != err { if nil != err {
log.Fatalln(err) log.Fatalln(err)
@@ -344,6 +275,27 @@ func reseedAction(c *cli.Context) {
} }
} }
if tlsHost != "" {
tlsKey = c.String("tlsKey")
// if no key is specified, default to the host.pem in the current dir
if tlsKey == "" {
tlsKey = tlsHost + ".pem"
}
tlsCert = c.String("tlsCert")
// if no certificate is specified, default to the host.crt in the current dir
if tlsCert == "" {
tlsCert = tlsHost + ".crt"
}
// prompt to create tls keys if they don't exist?
auto := c.Bool("yes")
err := checkOrNewTLSCert(tlsHost, &tlsCert, &tlsKey, auto)
if nil != err {
log.Fatalln(err)
}
}
reloadIntvl, err := time.ParseDuration(c.String("interval")) reloadIntvl, err := time.ParseDuration(c.String("interval"))
if nil != err { if nil != err {
fmt.Printf("'%s' is not a valid time interval.\n", reloadIntvl) fmt.Printf("'%s' is not a valid time interval.\n", reloadIntvl)
@@ -357,7 +309,7 @@ func reseedAction(c *cli.Context) {
} }
// load our signing privKey // load our signing privKey
auto := c.Bool("yes") auto := c.Bool("yes")
privKey, err := getOrNewSigningCert(&signerKey, signerID, auto) privKey, err := getOrNewSigningCert(&signerKey, signerID, auto)
if nil != err { if nil != err {
log.Fatalln(err) log.Fatalln(err)
@@ -410,7 +362,7 @@ func reseedAction(c *cli.Context) {
} }
} }
func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder *reseed.ReseederImpl) { func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder reseed.Reseeder) {
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy")) server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
server.Reseeder = reseeder server.Reseeder = reseeder
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
@@ -439,7 +391,7 @@ func reseedHTTPS(c *cli.Context, tlsCert, tlsKey string, reseeder *reseed.Reseed
} }
} }
func reseedHTTP(c *cli.Context, reseeder *reseed.ReseederImpl) { func reseedHTTP(c *cli.Context, reseeder reseed.Reseeder) {
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy")) server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
server.Reseeder = reseeder server.Reseeder = reseeder
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
@@ -476,7 +428,7 @@ func makeRandomHost(port int) (host.Host, error) {
return host, nil return host, nil
} }
func reseedP2P(c *cli.Context, reseeder *reseed.ReseederImpl) { func reseedP2P(c *cli.Context, reseeder reseed.Reseeder) {
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy")) server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
server.Reseeder = reseeder server.Reseeder = reseeder
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
@@ -514,7 +466,7 @@ func reseedP2P(c *cli.Context, reseeder *reseed.ReseederImpl) {
} }
} }
func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder *reseed.ReseederImpl) { func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder reseed.Reseeder) {
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy")) server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
server.Reseeder = reseeder server.Reseeder = reseeder
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))
@@ -589,7 +541,7 @@ func reseedOnion(c *cli.Context, onionTlsCert, onionTlsKey string, reseeder *res
log.Printf("Onion server started on %s\n", server.Addr) log.Printf("Onion server started on %s\n", server.Addr)
} }
func reseedI2P(c *cli.Context, i2pTlsCert, i2pTlsKey string, i2pIdentKey i2pkeys.I2PKeys, reseeder *reseed.ReseederImpl) { func reseedI2P(c *cli.Context, i2pTlsCert, i2pTlsKey string, i2pIdentKey i2pkeys.I2PKeys, reseeder reseed.Reseeder) {
server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy")) server := reseed.NewServer(c.String("prefix"), c.Bool("trustProxy"))
server.Reseeder = reseeder server.Reseeder = reseeder
server.Addr = net.JoinHostPort(c.String("ip"), c.String("port")) server.Addr = net.JoinHostPort(c.String("ip"), c.String("port"))

View File

@@ -2,12 +2,10 @@ package cmd
import ( import (
"bufio" "bufio"
"crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/tls"
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/asn1" "encoding/asn1"
@@ -18,15 +16,8 @@ import (
"strings" "strings"
"time" "time"
"i2pgit.org/idk/reseed-tools/reseed" "github.com/MDrollette/i2p-tools/reseed"
"i2pgit.org/idk/reseed-tools/su3" "github.com/MDrollette/i2p-tools/su3"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
) )
func loadPrivateKey(path string) (*rsa.PrivateKey, error) { func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
@@ -44,24 +35,6 @@ func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
return privKey, nil return privKey, nil
} }
// Taken directly from the lego example, since we need very minimal support
// https://go-acme.github.io/lego/usage/library/
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func signerFile(signerID string) string { func signerFile(signerID string) string {
return strings.Replace(signerID, "@", "_at_", 1) return strings.Replace(signerID, "@", "_at_", 1)
} }
@@ -69,14 +42,14 @@ func signerFile(signerID string) string {
func getOrNewSigningCert(signerKey *string, signerID string, auto bool) (*rsa.PrivateKey, error) { func getOrNewSigningCert(signerKey *string, signerID string, auto bool) (*rsa.PrivateKey, error) {
if _, err := os.Stat(*signerKey); nil != err { if _, err := os.Stat(*signerKey); nil != err {
fmt.Printf("Unable to read signing key '%s'\n", *signerKey) fmt.Printf("Unable to read signing key '%s'\n", *signerKey)
if !auto { if !auto {
fmt.Printf("Would you like to generate a new signing key for %s? (y or n): ", signerID) fmt.Printf("Would you like to generate a new signing key for %s? (y or n): ", signerID)
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n') input, _ := reader.ReadString('\n')
if []byte(input)[0] != 'y' { if []byte(input)[0] != 'y' {
return nil, fmt.Errorf("A signing key is required") return nil, fmt.Errorf("A signing key is required")
}
} }
}
if err := createSigningCertificate(signerID); nil != err { if err := createSigningCertificate(signerID); nil != err {
return nil, err return nil, err
} }
@@ -87,165 +60,6 @@ func getOrNewSigningCert(signerKey *string, signerID string, auto bool) (*rsa.Pr
return loadPrivateKey(*signerKey) return loadPrivateKey(*signerKey)
} }
func checkUseAcmeCert(tlsHost, signer, cadirurl string, tlsCert, tlsKey *string, auto bool) error {
_, certErr := os.Stat(*tlsCert)
_, keyErr := os.Stat(*tlsKey)
if certErr != nil || keyErr != nil {
if certErr != nil {
fmt.Printf("Unable to read TLS certificate '%s'\n", *tlsCert)
}
if keyErr != nil {
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
}
if !auto {
fmt.Printf("Would you like to generate a new certificate with Let's Encrypt or a custom ACME server? '%s'? (y or n): ", tlsHost)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
if []byte(input)[0] != 'y' {
fmt.Println("Continuing without TLS")
return nil
}
}
} else {
TLSConfig := &tls.Config{}
TLSConfig.NextProtos = []string{"http/1.1"}
TLSConfig.Certificates = make([]tls.Certificate, 1)
var err error
TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(*tlsCert, *tlsKey)
if err != nil {
return err
}
if time.Now().Sub(TLSConfig.Certificates[0].Leaf.NotAfter) < (time.Hour * 48) {
ecder, err := ioutil.ReadFile(tlsHost + signer + ".acme.key")
if err != nil {
return err
}
privateKey, err := x509.ParseECPrivateKey(ecder)
if err != nil {
return err
}
user := MyUser{
Email: signer,
key: privateKey,
}
config := lego.NewConfig(&user)
config.CADirURL = cadirurl
config.Certificate.KeyType = certcrypto.RSA2048
client, err := lego.NewClient(config)
if err != nil {
return err
}
renewAcmeIssuedCert(client, user, tlsHost, tlsCert, tlsKey)
} else {
return nil
}
}
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return err
}
ecder, err := x509.MarshalECPrivateKey(privateKey)
if err != nil {
return err
}
filename := tlsHost + signer + ".acme.key"
keypem, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer keypem.Close()
err = pem.Encode(keypem, &pem.Block{Type: "EC PRIVATE KEY", Bytes: ecder})
if err != nil {
return err
}
user := MyUser{
Email: signer,
key: privateKey,
}
config := lego.NewConfig(&user)
config.CADirURL = cadirurl
config.Certificate.KeyType = certcrypto.RSA2048
client, err := lego.NewClient(config)
if err != nil {
return err
}
return newAcmeIssuedCert(client, user, tlsHost, tlsCert, tlsKey)
}
func renewAcmeIssuedCert(client *lego.Client, user MyUser, tlsHost string, tlsCert, tlsKey *string) error {
var err error
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "8000"))
if err != nil {
return err
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "8443"))
if err != nil {
return err
}
// New users will need to register
if user.Registration, err = client.Registration.QueryRegistration(); err != nil {
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return err
}
user.Registration = reg
}
resource, err := client.Certificate.Get(tlsHost, true)
if err != nil {
return err
}
certificates, err := client.Certificate.Renew(*resource, true, false, "")
if err != nil {
return err
}
ioutil.WriteFile(tlsHost+".pem", certificates.PrivateKey, 0600)
ioutil.WriteFile(tlsHost+".crt", certificates.Certificate, 0600)
// ioutil.WriteFile(tlsHost+".crl", certificates.PrivateKey, 0600)
*tlsCert = tlsHost + ".crt"
*tlsKey = tlsHost + ".pem"
return nil
}
func newAcmeIssuedCert(client *lego.Client, user MyUser, tlsHost string, tlsCert, tlsKey *string) error {
var err error
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "8000"))
if err != nil {
return err
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "8443"))
if err != nil {
return err
}
// New users will need to register
if user.Registration, err = client.Registration.QueryRegistration(); err != nil {
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return err
}
user.Registration = reg
}
request := certificate.ObtainRequest{
Domains: []string{tlsHost},
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
return err
}
ioutil.WriteFile(tlsHost+".pem", certificates.PrivateKey, 0600)
ioutil.WriteFile(tlsHost+".crt", certificates.Certificate, 0600)
// ioutil.WriteFile(tlsHost+".crl", certificates.PrivateKey, 0600)
*tlsCert = tlsHost + ".crt"
*tlsKey = tlsHost + ".pem"
return nil
}
func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error { func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error {
_, certErr := os.Stat(*tlsCert) _, certErr := os.Stat(*tlsCert)
_, keyErr := os.Stat(*tlsKey) _, keyErr := os.Stat(*tlsKey)
@@ -257,7 +71,7 @@ func checkOrNewTLSCert(tlsHost string, tlsCert, tlsKey *string, auto bool) error
fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey) fmt.Printf("Unable to read TLS key '%s'\n", *tlsKey)
} }
if !auto { if auto {
fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost) fmt.Printf("Would you like to generate a new self-signed certificate for '%s'? (y or n): ", tlsHost)
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n') input, _ := reader.ReadString('\n')

View File

@@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"github.com/urfave/cli" "github.com/MDrollette/i2p-tools/reseed"
"i2pgit.org/idk/reseed-tools/reseed" "github.com/MDrollette/i2p-tools/su3"
"i2pgit.org/idk/reseed-tools/su3" "github.com/codegangsta/cli"
) )
func NewSu3VerifyCommand() cli.Command { func NewSu3VerifyCommand() cli.Command {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

View File

@@ -1,10 +0,0 @@
<h1 id="you-have-found-an-i2p-reseed">You have found an I2P Reseed</h1>
<p>Maybe it was by accident, or maybe you visited the URL because you saw it in the software somewhere. While weve got your attention, were going to take this opportunity to tell you a little about what we do here. I2P is a peer-to-peer network which uses “Garlic Routing” to maintain privacy. Reseed nodes help you get connected to I2P for the first time, and even though you should only have to use them once in a great while, they are very important services.</p>
<h2 id="to-learn-more-about-i2p-visit"><a href="https://geti2p.net">To learn more about I2P, visit</a></h2>
<p><a href="https://geti2p.net"><img src="images/reseed.png" alt="Help reseed" /></a></p>
<ul>
<li><a href="https://geti2p.net/en/docs/reseed">Learn more about reseeds here:</a></li>
<li><a href="https://geti2p.net/en/get-involved/guides/reseed">Learn how to run a reseed here:</a></li>
<li><a href="https://i2pgit.org/idk/reseed-tools">Read the reseed server code and learn about more reseed options here:</a></li>
</ul>
<p>Here on purpose? Heres a one-time link to a reseed bundle for you.</p>

View File

@@ -1,18 +0,0 @@
You have found an I2P Reseed
============================
Maybe it was by accident, or maybe you visited the URL because you saw it in the software somewhere. While we've got
your attention, we're going to take this opportunity to tell you a little about what we do here. I2P is a peer-to-peer
network which uses "Garlic Routing" to maintain privacy. Reseed nodes help you get connected to I2P for the first time,
and even though you should only have to use them once in a great while, they are very important services.
[To learn more about I2P, visit the project website](https://geti2p.net)
------------------------------------------------------------------------
[![Help reseed](images/reseed.png)](https://geti2p.net)
- [Learn more about reseeds here:](https://geti2p.net/en/docs/reseed)
- [Learn how to run a reseed here:](https://geti2p.net/en/get-involved/guides/reseed)
- [Read the reseed server code and learn about more reseed options here:](https://i2pgit.org/idk/reseed-tools)
### Here on purpose? Here's a one-time link to a reseed bundle for you.

View File

View File

@@ -1,37 +0,0 @@
body {
font-family: monospace;
text-align: justify;
}
h1 {
text-align: center;
}
img {
display: block;
margin-left: auto;
margin-right: auto;
width: 50%;
}
.inline {
display: inline;
}
.link-button {
background: none;
border: none;
color: blue;
text-decoration: underline;
cursor: pointer;
font-size: 1em;
font-family: serif;
}
.link-button:focus {
outline: none;
}
.link-button:active {
color:red;
}

View File

@@ -1,2 +0,0 @@
Reseed tools is a self-contained, easy-to-configure I2P reseed service
which can be run on any OS.

View File

@@ -1,5 +0,0 @@
#! /usr/bin/env sh
cp -r /var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/content ./content
/var/lib/i2p/go/src/i2pgit.org/idk/reseed-tools/reseed-tools reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb $@

View File

@@ -1,2 +0,0 @@
#Edit the contact/signing email used by your reseed server here
export RESEED_EMAIL=""

View File

@@ -8,31 +8,42 @@
# Description: <DESCRIPTION> # Description: <DESCRIPTION>
### END INIT INFO ### END INIT INFO
SCRIPT='/usr/bin/reseed-tools' SCRIPT='/usr/local/bin/i2p-tools'
RUNAS=i2psvc RUNAS=i2psvc
NETDBDIR=/var/lib/i2p/i2p-config/netDb NETDBDIR=/var/lib/i2p/i2p-config/netDb
RUNDIR=/var/lib/i2p/i2p-config/reseed RUNDIR=/var/lib/i2p/i2p-config/reseed
SIGNER=you@mail.i2p
MORE_OPTIONS="" MORE_OPTIONS=""
if [ -f /etc/default/reseed ]; then if [ -f /etc/default/reseed ]; then
. /etc/default/reseed source /etc/default/reseed
fi fi
RUNOPTS=" reseed --yes=true --netdb=$NETDBDIR $MORE_OPTIONS " RUNOPTS=" reseed --signer=$SIGNER --netdb=$NETDBDIR $MORE_OPTIONS "
rundir(){
if [ !-d $RUNDIR ]; then
install -d -oi2psvc -m2770 $RUNDIR
fi
cd $RUNDIR
}
start() { start() {
start-stop-daemon --user $RUNAS --exec $SCRIPT --chdir $RUNDIR --make-pidfile $RUNDIR/reseed.pid --start -- $RUNOPTS rundir
su - $RUNAS $SCRIPT $RUNOPTS --restart=start
} }
stop() { stop() {
start-stop-daemon --user $RUNAS --exec $SCRIPT --chdir $RUNDIR --remove-pidfile $RUNDIR/reseed.pid --stop rundir
su - $RUNAS $SCRIPT $RUNOPTS --restart=stop
}
start() {
rundir
su - $RUNAS $SCRIPT $RUNOPTS --restart=restart
} }
status() { status() {
start-stop-daemon --user $RUNAS --exec $SCRIPT --chdir $RUNDIR --remove-pidfile $RUNDIR/reseed.pid --status rundir
} su - $RUNAS $SCRIPT $RUNOPTS --restart=status
restart() {
stop
start
} }
uninstall() { uninstall() {

View File

@@ -1,5 +0,0 @@
# Use this file to configure the contact/signer email used for the reseed service.
# without it the reseed will fail to start.
[Service]
Environment="RESEED_EMAIL="

View File

@@ -1,17 +0,0 @@
[Unit]
Description=I2P reseed service
After=network.target
StartLimitIntervalSec=0
Requires=i2p.service
[Service]
User=i2psvc
RuntimeDirectory=/var/lib/i2p/i2p-config/reseed
WorkingDirectory=/var/lib/i2p/i2p-config/reseed
ExecStart=/usr/bin/reseed-tools reseed --yes=true --netdb=/var/lib/i2p/i2p-config/netDb
Restart=always
RestartSec=10
RuntimeMaxSec=43200
[Install]
WantedBy=multi-user.target

33
go.mod
View File

@@ -1,20 +1,25 @@
module i2pgit.org/idk/reseed-tools module github.com/eyedeekay/i2p-tools-1
go 1.13 go 1.13
require ( require (
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce // indirect
github.com/MDrollette/i2p-tools v0.0.0
github.com/codegangsta/cli v1.22.1
github.com/cretz/bine v0.1.0 github.com/cretz/bine v0.1.0
github.com/eyedeekay/checki2cp v0.0.21 // indirect github.com/eyedeekay/sam3 v0.32.2
github.com/eyedeekay/sam3 v0.32.32 github.com/gomodule/redigo v1.8.0 // indirect
github.com/go-acme/lego/v4 v4.3.1 github.com/gorilla/handlers v1.4.2
github.com/gorilla/handlers v1.5.1 github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da
github.com/justinas/alice v1.2.0 github.com/libp2p/go-libp2p v0.6.0
github.com/libp2p/go-libp2p v0.13.0 github.com/libp2p/go-libp2p-core v0.5.0
github.com/libp2p/go-libp2p-core v0.8.0 github.com/libp2p/go-libp2p-gostream v0.2.1
github.com/libp2p/go-libp2p-gostream v0.3.1 github.com/libp2p/go-libp2p-http v0.1.5
github.com/libp2p/go-libp2p-http v0.2.0 github.com/shurcooL/go v0.0.0-20190704215121-7189cc372560 // indirect
github.com/throttled/throttled/v2 v2.7.1 github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 // indirect
github.com/urfave/cli v1.22.5 github.com/throttled/throttled v2.2.4+incompatible
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19
golang.org/x/text v0.3.5
) )
replace github.com/MDrollette/i2p-tools v0.0.0 => ./
replace github.com/codegangsta/cli v1.22.1 => github.com/urfave/cli v1.22.1

1103
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -41,4 +41,4 @@
* numRi per su3 file: 75 --> 77 * numRi per su3 file: 75 --> 77
2016-01 2016-01
* fork from https://i2pgit.org/idk/reseed-tools * fork from https://github.com/MDrollette/i2p-tools

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"runtime" "runtime"
"github.com/urfave/cli" "github.com/MDrollette/i2p-tools/cmd"
"i2pgit.org/idk/reseed-tools/cmd" "github.com/codegangsta/cli"
) )
func main() { func main() {
@@ -18,8 +18,8 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU() / 2) runtime.GOMAXPROCS(runtime.NumCPU() / 2)
app := cli.NewApp() app := cli.NewApp()
app.Name = "reseed-tools" app.Name = "i2p-tools-1"
app.Version = "0.1.9" app.Version = "0.1.7"
app.Usage = "I2P tools and reseed server" app.Usage = "I2P tools and reseed server"
app.Author = "eyedeekay" app.Author = "eyedeekay"
app.Email = "hankhill19580@gmail.com" app.Email = "hankhill19580@gmail.com"

View File

@@ -1,35 +0,0 @@
#! /usr/bin/env sh
RESEED_MESSAGE="Reseed Tools requires you to set an email for contact purposes.
This is in case your reseed goes down.
Please enter your email below."
RESEED_CONF="# Use this file to configure the contact/signer email used for the reseed service.
# without it the reseed will fail to start.
[Service]
Environment=\"RESEED_EMAIL="
RESEED_DEFAULT="#Edit the contact/signing email used by your reseed server here
export RESEED_EMAIL=\""
mkdir -p /etc/systemd/system/reseed.d/
if [ -f /usr/bin/zenity ]; then
RESEED_EMAIL=$(zenity --entry --title "Reseed Configuration" --text "$RESEED_MESSAGE" 10 30 3>&1 1>&2 2>&3)
echo "$RESEED_DEFAULT$RESEED_EMAIL\"" >> /etc/default/reseed
echo "$RESEED_CONF$RESEED_EMAIL\"" >> /etc/systemd/system/reseed.d/reseed.conf
exit 0
fi
if [ -t 1 ] ; then
echo "proceeding with terminal";
else
exit 0
fi
if [ -f /usr/bin/whiptail ]; then
RESEED_EMAIL=$(whiptail --inputbox "$RESEED_MESSAGE" 10 30 3>&1 1>&2 2>&3)
echo "$RESEED_DEFAULT$RESEED_EMAIL\"" >> /etc/default/reseed
echo "$RESEED_CONF$RESEED_EMAIL\"" >> /etc/systemd/system/reseed.d/reseed.conf
exit 0
fi

View File

@@ -1,132 +0,0 @@
package reseed
import (
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"gitlab.com/golang-commonmark/markdown"
"golang.org/x/text/language"
)
var SupportedLanguages = []language.Tag{
language.English,
}
var CachedLanguagePages = map[string]string{}
var CachedDataPages = map[string][]byte{}
var BaseContentPath, ContentPathError = ContentPath()
var matcher = language.NewMatcher(SupportedLanguages)
var header = []byte(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>This is an I2P Reseed Server</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>`)
var footer = []byte(` </body>
</html>`)
var md = markdown.New(markdown.XHTMLOutput(true), markdown.HTML(true))
func ContentPath() (string, error) {
exPath, err := os.Getwd()
if err != nil {
return "", err
}
//exPath := filepath.Dir(ex)
if _, err := os.Stat(filepath.Join(exPath, "content")); err != nil {
return "", err
}
return filepath.Join(exPath, "content"), nil
}
func (srv *Server) HandleARealBrowser(w http.ResponseWriter, r *http.Request) {
if ContentPathError != nil {
http.Error(w, "403 Forbidden", http.StatusForbidden)
return
}
lang, _ := r.Cookie("lang")
accept := r.Header.Get("Accept-Language")
tag, _ := language.MatchStrings(matcher, lang.String(), accept)
base, _ := tag.Base()
switch r.URL.Path {
case "/style.css":
w.Header().Set("Content-Type", "text/css")
HandleAFile(w, "", "style.css")
case "/script.js":
w.Header().Set("Content-Type", "text/javascript")
HandleAFile(w, "", "script.js")
default:
image := strings.Replace(r.URL.Path, "/", "", -1)
if strings.HasPrefix(image, "images") {
w.Header().Set("Content-Type", "image/png")
HandleAFile(w, "images", strings.TrimPrefix(strings.TrimPrefix(r.URL.Path, "/"), "images"))
} else {
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(header))
HandleALocalizedFile(w, base.String())
w.Write([]byte(`<ul><li><form method="post" action="/i2pseeds" class="inline">
<input type="hidden" name="onetime" value="` + srv.Acceptable() + `">
<button type="submit" name="submit_param" value="submit_value" class="link-button">
Bundle
</button>
</form></li></ul>`))
w.Write([]byte(footer))
}
}
}
func HandleAFile(w http.ResponseWriter, dirPath, file string) {
file = filepath.Join(dirPath, file)
if _, prs := CachedDataPages[file]; prs == false {
path := filepath.Join(BaseContentPath, file)
f, err := ioutil.ReadFile(path)
if err != nil {
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
return
}
CachedDataPages[file] = f
w.Write([]byte(CachedDataPages[file]))
} else {
w.Write(CachedDataPages[file])
}
}
func HandleALocalizedFile(w http.ResponseWriter, dirPath string) {
if _, prs := CachedLanguagePages[dirPath]; prs == false {
dir := filepath.Join(BaseContentPath, "lang", dirPath)
files, err := ioutil.ReadDir(dir)
if err != nil {
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
}
var f []byte
for _, file := range files {
if !strings.HasSuffix(file.Name(), ".md") {
return
}
trimmedName := strings.TrimSuffix(file.Name(), ".md")
path := filepath.Join(dir, file.Name())
b, err := ioutil.ReadFile(path)
if err != nil {
w.Write([]byte("Oops! Something went wrong handling your language. Please file a bug at https://i2pgit.org/idk/reseed-tools\n\t" + err.Error()))
return
}
f = append(f, []byte(`<div id="`+trimmedName+`">`)...)
f = append(f, []byte(md.RenderToString(b))...)
f = append(f, []byte(`</div>`)...)
}
CachedLanguagePages[dirPath] = string(f)
w.Write([]byte(CachedLanguagePages[dirPath]))
} else {
w.Write([]byte(CachedLanguagePages[dirPath]))
}
}

View File

@@ -3,7 +3,6 @@ package reseed
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/rand"
"crypto/tls" "crypto/tls"
"io" "io"
"log" "log"
@@ -21,8 +20,8 @@ import (
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
gostream "github.com/libp2p/go-libp2p-gostream" gostream "github.com/libp2p/go-libp2p-gostream"
p2phttp "github.com/libp2p/go-libp2p-http" p2phttp "github.com/libp2p/go-libp2p-http"
throttled "github.com/throttled/throttled/v2" "github.com/throttled/throttled"
"github.com/throttled/throttled/v2/store" "github.com/throttled/throttled/store"
) )
const ( const (
@@ -35,10 +34,9 @@ type Server struct {
I2PSession *sam3.StreamSession I2PSession *sam3.StreamSession
I2PListener *sam3.StreamListener I2PListener *sam3.StreamListener
I2PKeys i2pkeys.I2PKeys I2PKeys i2pkeys.I2PKeys
Reseeder *ReseederImpl Reseeder Reseeder
Blacklist *Blacklist Blacklist *Blacklist
OnionListener *tor.OnionService OnionListener *tor.OnionService
acceptables map[string]time.Time
} }
func NewServer(prefix string, trustProxy bool) *Server { func NewServer(prefix string, trustProxy bool) *Server {
@@ -67,7 +65,6 @@ func NewServer(prefix string, trustProxy bool) *Server {
server := Server{Server: h, Reseeder: nil} server := Server{Server: h, Reseeder: nil}
th := throttled.RateLimit(throttled.PerHour(4), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000)) th := throttled.RateLimit(throttled.PerHour(4), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000))
thw := throttled.RateLimit(throttled.PerHour(30), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(200000))
middlewareChain := alice.New() middlewareChain := alice.New()
if trustProxy { if trustProxy {
@@ -82,85 +79,13 @@ func NewServer(prefix string, trustProxy bool) *Server {
}) })
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle("/", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, thw.Throttle, server.browsingMiddleware).Then(errorHandler)) mux.Handle("/", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware).Then(errorHandler))
mux.Handle(prefix+"/i2pseeds.su3", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, verifyMiddleware, th.Throttle).Then(http.HandlerFunc(server.reseedHandler))) mux.Handle(prefix+"/i2pseeds.su3", middlewareChain.Append(disableKeepAliveMiddleware, loggingMiddleware, verifyMiddleware, th.Throttle).Then(http.HandlerFunc(server.reseedHandler)))
server.Handler = mux server.Handler = mux
return &server return &server
} }
// See use of crypto/rand on:
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
const (
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52 possibilities
letterIdxBits = 6 // 6 bits to represent 64 possibilities / indexes
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
)
func SecureRandomAlphaString() string {
length := 16
result := make([]byte, length)
bufferSize := int(float64(length) * 1.3)
for i, j, randomBytes := 0, 0, []byte{}; i < length; j++ {
if j%bufferSize == 0 {
randomBytes = SecureRandomBytes(bufferSize)
}
if idx := int(randomBytes[j%length] & letterIdxMask); idx < len(letterBytes) {
result[i] = letterBytes[idx]
i++
}
}
return string(result)
}
// SecureRandomBytes returns the requested number of bytes using crypto/rand
func SecureRandomBytes(length int) []byte {
var randomBytes = make([]byte, length)
_, err := rand.Read(randomBytes)
if err != nil {
log.Fatal("Unable to generate random bytes")
}
return randomBytes
}
//
func (srv *Server) Acceptable() string {
if srv.acceptables == nil {
srv.acceptables = make(map[string]time.Time)
}
if len(srv.acceptables) > 50 {
for val := range srv.acceptables {
srv.CheckAcceptable(val)
}
for val := range srv.acceptables {
if len(srv.acceptables) < 50 {
break
}
delete(srv.acceptables, val)
}
}
acceptme := SecureRandomAlphaString()
srv.acceptables[acceptme] = time.Now()
return acceptme
}
func (srv *Server) CheckAcceptable(val string) bool {
if srv.acceptables == nil {
srv.acceptables = make(map[string]time.Time)
}
if timeout, ok := srv.acceptables[val]; ok {
checktime := time.Now().Sub(timeout)
if checktime > (4 * time.Minute) {
delete(srv.acceptables, val)
return false
}
delete(srv.acceptables, val)
return true
}
return false
}
func (srv *Server) ListenAndServe() error { func (srv *Server) ListenAndServe() error {
addr := srv.Addr addr := srv.Addr
if addr == "" { if addr == "" {
@@ -320,7 +245,7 @@ func (srv *Server) ListenAndServeI2P(samaddr string, I2PKeys i2pkeys.I2PKeys) er
if err != nil { if err != nil {
return err return err
} }
log.Printf("I2P server started on http://%v.b32.i2p\n", srv.I2PListener.Addr().(i2pkeys.I2PAddr).Base32()) log.Printf("I2P server started on http://%v.onion\n", srv.OnionListener.ID)
return srv.Serve(srv.I2PListener) return srv.Serve(srv.I2PListener)
} }
@@ -366,20 +291,6 @@ func loggingMiddleware(next http.Handler) http.Handler {
return handlers.CombinedLoggingHandler(os.Stdout, next) return handlers.CombinedLoggingHandler(os.Stdout, next)
} }
func (srv *Server) browsingMiddleware(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if srv.CheckAcceptable(r.FormValue("onetime")) {
srv.reseedHandler(w, r)
}
if i2pUserAgent != r.UserAgent() {
srv.HandleARealBrowser(w, r)
return
}
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func verifyMiddleware(next http.Handler) http.Handler { func verifyMiddleware(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) { fn := func(w http.ResponseWriter, r *http.Request) {
if i2pUserAgent != r.UserAgent() { if i2pUserAgent != r.UserAgent() {

View File

@@ -15,7 +15,7 @@ import (
"sync" "sync"
"time" "time"
"i2pgit.org/idk/reseed-tools/su3" "github.com/MDrollette/i2p-tools/su3"
) )
type routerInfo struct { type routerInfo struct {
@@ -33,13 +33,13 @@ func (p Peer) Hash() int {
return int(crc32.ChecksumIEEE(c)) return int(crc32.ChecksumIEEE(c))
} }
/*type Reseeder interface { type Reseeder interface {
// get an su3 file (bytes) for a peer // get an su3 file (bytes) for a peer
PeerSu3Bytes(peer Peer) ([]byte, error) PeerSu3Bytes(peer Peer) ([]byte, error)
}*/ }
type ReseederImpl struct { type ReseederImpl struct {
netdb *LocalNetDbImpl netdb NetDbProvider
su3s chan [][]byte su3s chan [][]byte
SigningKey *rsa.PrivateKey SigningKey *rsa.PrivateKey
@@ -49,7 +49,7 @@ type ReseederImpl struct {
NumSu3 int NumSu3 int
} }
func NewReseeder(netdb *LocalNetDbImpl) *ReseederImpl { func NewReseeder(netdb NetDbProvider) *ReseederImpl {
return &ReseederImpl{ return &ReseederImpl{
netdb: netdb, netdb: netdb,
su3s: make(chan [][]byte), su3s: make(chan [][]byte),
@@ -224,10 +224,10 @@ func (rs *ReseederImpl) createSu3(seeds []routerInfo) (*su3.File, error) {
return su3File, nil return su3File, nil
} }
/*type NetDbProvider interface { type NetDbProvider interface {
// Get all router infos // Get all router infos
RouterInfos() ([]routerInfo, error) RouterInfos() ([]routerInfo, error)
}*/ }
type LocalNetDbImpl struct { type LocalNetDbImpl struct {
Path string Path string

View File

@@ -23,20 +23,16 @@ const (
SigTypeRSAWithSHA384 = uint16(5) SigTypeRSAWithSHA384 = uint16(5)
SigTypeRSAWithSHA512 = uint16(6) SigTypeRSAWithSHA512 = uint16(6)
ContentTypeUnknown = uint8(0) ContentTypeUnknown = uint8(0)
ContentTypeRouter = uint8(1) ContentTypeRouter = uint8(1)
ContentTypePlugin = uint8(2) ContentTypePlugin = uint8(2)
ContentTypeReseed = uint8(3) ContentTypeReseed = uint8(3)
ContentTypeNews = uint8(4) ContentTypeNews = uint8(4)
ContentTypeBlocklist = uint8(5)
FileTypeZIP = uint8(0) FileTypeZIP = uint8(0)
FileTypeXML = uint8(1) FileTypeXML = uint8(1)
FileTypeHTML = uint8(2) FileTypeHTML = uint8(2)
FileTypeXMLGZ = uint8(3) FileTypeXMLGZ = uint8(3)
FileTypeTXTGZ = uint8(4)
FileTypeDMG = uint8(5)
FileTypeEXE = uint8(6)
magicBytes = "I2Psu3" magicBytes = "I2Psu3"
) )