This commit is contained in:
Willem@105.pve1.lan 2022-02-20 12:43:00 +02:00
commit 29c53726c1
31 changed files with 577 additions and 28 deletions

10
.gitignore vendored
View File

@ -1,10 +0,0 @@
# Logo
/logo.png
# Build executables
/build
/cmd/boringproxy/boringproxy*
boringproxy_*.tar.gz
# Boringproxy database, created if exec is run in boringproxy folder
boringproxy_db.json

62
CHANGELOG.md Normal file
View File

@ -0,0 +1,62 @@
# v0.9.0
* Fix bug where client doesn't automatically detect user because the client
defaulted to "admin" when no user was provided.
# v0.9.0
* Raw TLS tunnels implemented, which adds WebSockets support.
* Improved security of tokens. They can now be limited to only work for
specific clients.
* A default logo is included in the repo, so inkscape is no longer required to
build the project (thanks @WGrobler!).
* Docker instructions, scripts, and examples greatly improved (thanks
@WGRobler!)
* Added IPv6 support.
* API simplified so client doesn't need to be run with `-user` or
`-client-name` if that information can be extracted from the token.
* Added `-acme-use-staging` to allow use of Let's Encrypt staging servers.
* Added page to allow managing clients from the web UI. Previously they were
silently added when the client first connected.
* Added `-behind-proxy` flag so X-Forwarded-For header is only added when the
flag is set. This improves security so clients can't spoof their IPs.
# v0.8.2
* Integration with [TakingNames.io](https://takingnames.io).
* Support now available through the [IndieBits forum](https://forum.indiebits.io/).
* Switch to more traditional HTML UI. Was doing some cool but hacky CSS stuff.
* Replaced go.rice with embed from stdlib.
* Check if ports are publicly accessible on startup.
* Add individual pages to look at tunnel details.
* Implement support for unencrypted HTTP.
* Can now select server HTTP/HTTPS ports.
* Add Forwarded and X-Forwarded-For proxy headers.
* Implement printing login link as QR code on the command line.
# v0.7.0
* Fixed server authorized_key file getting huge.
* Added FreeBSD and OpenBSD builds.
* Fix redirects on client-terminated tunnels.
# v0.6.0
* Various internal improvements, especially to make boringproxy easier to use as a library in other programs.
* Renamed amd64 to x86_64 to be easier to distinguish from arm64.
* Allow tunnel port to be selected, allowing boringproxy to more easily be used like a normal reverse proxy.
* Various other small bug fixes and UX improvements.
# v0.5.0
* Improved UX
* Print usage information (thanks @arp242!)
* Some better error messages
* Added systemd docs and examples (thanks @voidrot!)
* Move main package into cmd/boringproxy so server and client can be imported into other programs.
* Stream requests. Server was reading entire requests before forwarding to upstream (similar to nginx default). Now streams everything.

View File

@ -1,19 +1,32 @@
FROM golang:1.17-alpine3.15 as builder
LABEL boringproxy=builder
ARG VERSION
ARG GOOS="linux"
ARG GOARCH="amd64"
ARG BRANCH="master"
ARG REPO="https://github.com/boringproxy/boringproxy.git"
ARG ORIGIN='local'
WORKDIR /build
RUN apk add git
RUN if [[ "ORIGIN" == 'remote' ]] ; then git clone --depth 1 --branch "${BRANCH}" ${REPO}; fi
COPY go.* ./
RUN go mod download
COPY . .
RUN export VERSION='2'
RUN cd cmd/boringproxy && CGO_ENABLED=0 go build -o boringproxy
RUN cd cmd/boringproxy && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} \
go build -ldflags "-X main.Version=${VERSION}" \
-o boringproxy
FROM scratch
FROM scratch
EXPOSE 80 443
COPY --from=builder /build/cmd/boringproxy/boringproxy /
ENTRYPOINT ["/boringproxy"]
CMD ["server"]
CMD ["version"]

View File

@ -133,7 +133,7 @@ func Listen() {
users := db.GetUsers()
if len(users) == 0 {
db.AddUser("admin", true)
_, err := db.AddToken("admin", "any")
_, err := db.AddToken("admin", "")
if err != nil {
log.Fatal("Failed to initialize admin user")
}

View File

@ -140,7 +140,7 @@ func (c *Client) Run(ctx context.Context) error {
}
msg := string(body)
return errors.New(fmt.Sprintf("Failed to create client. Are the user (%s) and token correct? HTTP Status code: %d. Message: %s", c.user, resp.StatusCode, msg))
return errors.New(fmt.Sprintf("Failed to create client. Are the user ('%s') and token correct? HTTP Status code: %d. Message: %s", c.user, resp.StatusCode, msg))
}
for {

View File

@ -47,7 +47,7 @@ func main() {
server := flagSet.String("server", "", "boringproxy server")
token := flagSet.String("token", "", "Access token")
name := flagSet.String("client-name", "", "Client name")
user := flagSet.String("user", "admin", "user")
user := flagSet.String("user", "", "user")
certDir := flagSet.String("cert-dir", "", "TLS cert directory")
acmeEmail := flagSet.String("acme-email", "", "Email for ACME (ie Let's Encrypt)")
acmeUseStaging := flagSet.Bool("acme-use-staging", false, "Use ACME (ie Let's Encrypt) staging servers")

BIN
default_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

2
docker/.gitignore vendored
View File

@ -1,2 +0,0 @@
# Docker-compose file with local dev config
dev.yml

33
docker/client/README.md Normal file
View File

@ -0,0 +1,33 @@
# Files to run client using docker
## Update compose file
Edit docker-compose.yml and change the following under **commands** for service **boringproxy**
- bp.example.com: your admin domain
- your-user-token: token generated by your server
- your-client-name: the name to identify your client
- your-user-name: the user associated with the server token
### certmagic
The certmagic volume is used to store certificats. This directory must also be passed to the container with the -cert-dir command.
==If you make changes to this, make sure that the data in certmagic is persistent, otherwise new certificates will be generated everytime the container is started. This can result in triggering the [rate limits for Let's Encrypt](https://letsencrypt.org/docs/rate-limits/)==
### /etc/ssl/certs
Alpine doesn't include ca-certificates in the docker base image. You can add your OS ca-certificates to the docker container by linking your local certs directory to the image
- /etc/ssl/certs/:/etc/ssl/certs/:ro
## Build image from source and run server in docker
You can build the image from source. This requires that you clone the GitHub repo and start docker using the compose command below:
```bash
docker-compose -f docker-compose.yml -f source.yml up -d
```
## Download prebuild image and run server in docker
If you don't want to build the image, a prebuild image can be downloaded from GitHub. Start docker using the compose commands below to download the image and start the container.
```bash
docker-compose -f docker-compose.yml -f prebuild.yml up -d
```

View File

@ -0,0 +1,12 @@
version: '3.7'
services:
boringproxy:
container_name: boringproxy-client
restart: unless-stopped
command: ["client", "-server", "bp.example.com", "-token", "your-user-token", "-client-name", "your-client-name", "-user", "your-user-name", "-cert-dir", "/certmagic"]
volumes:
- certmagic:/certmagic
- /etc/ssl/certs/:/etc/ssl/certs/:ro
volumes:
certmagic:

View File

@ -0,0 +1,7 @@
# Boringproxy docker examples
The docker examples for boringproxy clients are set up to enable easy integration between boringproxy and popular self hosted services.
## Usage
To start using an example, copy the example content over to a local folder and start the containers using the `start.sh` script
These compose files use prebuild images, if you want to build images yourself, follow the instructions in the parent folder to set up your own compose files.

View File

@ -1,7 +0,0 @@
# Ignore everything in config
config/*
# But not these files...
!config/configuration.yaml
# Ignore everything in development config
dev-config/*

View File

@ -0,0 +1,26 @@
# FUse boringproxy with home-assistant
## Update compose file
Edit docker-compose.yml and change the following under **commands** for service **boringproxy**
- bp.example.com: your admin domain
- your-user-token: token generated by your server
- your-user-name: the user associated with the server token
## Add tunnel in WebUI
Add new tunnel with the following config
- Domain: domain for this tunnel
- Tunnel Type: **Client TSL**
- Tunnel Port: **Random**
- Client Name: **docker-homeassistant**
- Client Address: **homeassistant**
- Client Port: **8123**
## Start containers
To start the container(s), run the start script in the example folder
```bash
./start.sh
```

View File

@ -0,0 +1,10 @@
# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:
http:
# For extra security Homeassistant blocks proxy requests unless forwaring is set
use_x_forwarded_for: true
# If you changed the IP address of boringproxy in your docker-compose file, add the correct IP address here
trusted_proxies:
- 10.5.0.2

View File

@ -0,0 +1,38 @@
version: '3.7'
services:
boringproxy:
image: ghcr.io/wgrobler/boringproxy:latest
restart: unless-stopped
command: ["client", "-server", "bp.example.com", "-token", "your-user-token", "-client-name", "docker-homeassistant", "-user", "your-user-name", "-cert-dir", "/certmagic"]
volumes:
- certmagic:/certmagic
- /etc/ssl/certs/:/etc/ssl/certs/:ro
networks:
vpcbr:
ipv4_address: 10.5.0.2
homeassistant:
hostname: homeassistant
restart: unless-stopped
image: ghcr.io/home-assistant/home-assistant:latest
privileged: true
ports:
- "8123:8123" # Enable port on local machine, can be removed if you only want to use the tunnel
volumes:
- ./config:/config # Path to your home assistant config folder
- /etc/localtime:/etc/localtime:ro
networks:
vpcbr:
ipv4_address: 10.5.0.3
volumes:
certmagic:
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1

View File

@ -0,0 +1,6 @@
#!/bin/bash
export COMPOSE_PROJECT_NAME="bpc-homeassistant"
docker-compose down; # Stop containers if running
docker-compose up -d;
docker-compose logs -f;

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker-compose down

View File

@ -0,0 +1,26 @@
# FUse boringproxy with nginx
## Update compose file
Edit docker-compose.yml and change the following under **commands** for service **boringproxy**
- bp.example.com: your admin domain
- your-user-token: token generated by your server
- your-user-name: the user associated with the server token
## Add tunnel in WebUI
Add new tunnel with the following config
- Domain: domain for this tunnel
- Tunnel Type: **Client TSL**
- Tunnel Port: **Random**
- Client Name: **docker-nginx**
- Client Address: **nginx**
- Client Port: **8123**
## Start containers
To start the container(s), run the start script in the example folder
```bash
./start.sh
```

View File

@ -0,0 +1,19 @@
version: '3.7'
services:
boringproxy:
image: ghcr.io/wgrobler/boringproxy:latest
restart: unless-stopped
command: ["client", "-server", "bp.example.com", "-token", "your-user-token", "-client-name", "docker-nginx", "-user", "your-user-name","-cert-dir", "/certmagic"]
volumes:
- certmagic:/certmagic
- /etc/ssl/certs/:/etc/ssl/certs/:ro
nginx:
image: nginx:1.17
hostname: nginx
ports:
- 8080:80 # Enable port on local machine, can be removed if you only want to use the tunnel
volumes:
certmagic:

View File

@ -0,0 +1,6 @@
#!/bin/bash
export COMPOSE_PROJECT_NAME="bpc-nginx"
docker-compose down; # Stop containers if running
docker-compose up -d;
docker-compose logs -f;

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker-compose down

View File

@ -0,0 +1,4 @@
version: '3.7'
services:
boringproxy:
image: ghcr.io/wgrobler/boringproxy:latest

5
docker/client/source.yml Normal file
View File

@ -0,0 +1,5 @@
version: '3.7'
services:
boringproxy:
image: boringproxy
build: ../../

20
docker/server/README.md Normal file
View File

@ -0,0 +1,20 @@
# Files to run server using docker
## Update compose file
Edit docker-compose.yml and change the following under **commands** for service **boringproxy**
- bp.example.com: your admin domain
## Build image from source and run server in docker
You can build the image from source. This requires that you clone the GitHub repo and start docker using the compose command below:
```bash
docker-compose -f docker-compose.yml -f source.yml up -d
```
## Download prebuild image and run server in docker
If you don't want to build the image, a prebuild image can be downloaded from GitHub. Start docker using the compose commands below to download the image and start the container.
```bash
docker-compose -f docker-compose.yml -f prebuild.yml up -d
```

View File

@ -0,0 +1,14 @@
version: '3.7'
services:
boringproxy:
container_name: boringproxy-server
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- data:/opt/boringproxy/
command: ["server", "-admin-domain", "bp.example.com"]
volumes:
data:

View File

@ -0,0 +1,4 @@
version: '3.7'
services:
boringproxy:
image: ghcr.io/wgrobler/boringproxy:latest

5
docker/server/source.yml Normal file
View File

@ -0,0 +1,5 @@
version: '3.7'
services:
boringproxy:
image: boringproxy
build: ../../

220
scripts/build_docker.sh Executable file
View File

@ -0,0 +1,220 @@
#!/bin/bash
# Run from root boringproxy folder and call with ./scripts/build_docker.sh
############################################################
# Help #
############################################################
Help()
{
# Display Help
echo "Script to buid BoringProxy executables using docker"
echo "Syntax: build_docker.sh [h|help|local|remote]"
echo
echo "h & help: Display help documetation"
echo
echo "local: Build executables from local repo (current folder)"
echo "options:"
echo " a|arch Architecture to build for build (amd64,arm,arm64)"
echo " os Operating System to build for (linux,freebsd,openbsd,windows,darwin)"
echo " o|output Output format (image,exec)"
echo "example: "
echo " build_docker.sh local -a=amd -s=linux -o=image"
echo
echo "local: Build executables remote repo (Github fork)"
echo "options:"
echo " a|arch Architecture to build for build (amd64,arm,arm64)"
echo " os Operating System to build for (linux,freebsd,openbsd,windows,darwin)"
echo " u|user Github user"
echo " b|branch Branch/Tree"
echo " o|output Output format (image,exec)"
echo "example: "
echo " generate_docker.sh remote -a=amd -s=linux -u=wgrobler -b=dev -o=exec"
echo
}
############################################################
############################################################
# Main program #
############################################################
############################################################
# Check if file was run from correct working directory, if correct script file will exists
FILE=./scripts/build_docker.sh
if [ ! -f "$FILE" ]; then
echo "Script needs to be run from root boringproxy folder, call with ./scripts/build_docker.sh"
exit;
fi
if [ -z "$1" ];
then
echo "No input variabled supplied"
echo "Here is the script help documentation:"
echo
Help
exit;
else
if [ "$1" == "help" ] || [ "$1" == "h" ];
then
Help
exit;
fi
if [ "$1" == "local" ];
then
CMD='local'
GOARCH='amd64';
GOOS='linux';
OUTPUT_FORMAT='image';
# Get the options
for i in "$@"; do
case $i in
-a=*|--arch=*)
GOARCH="${i#*=}";
shift;
;;
-os=*)
GOOS="${i#*=}";
shift;
;;
-o=*|--output=*)
OUTPUT_FORMAT="${i#*=}";
shift;
;;
-*|--*)
echo "Unknown option $i"
exit 1
;;
*)
;;
esac
done
fi
if [ "$1" == "remote" ];
then
CMD='remote'
GOARCH='amd64';
GOOS='linux';
BRANCH='master';
GITHUB_USER="boringproxy"
OUTPUT_FORMAT='image';
# Get the options
for i in "$@"; do
case $i in
-a=*|--arch=*)
GOARCH="${i#*=}";
shift;
;;
-os=*)
GOOS="${i#*=}";
shift;
;;
-b=*|--branch=*)
BRANCH="${i#*=}";
shift;
;;
-u=*|--user=*)
GITHUB_USER="${i#*=}";
shift;
;;
-o=*|--output=*)
OUTPUT_FORMAT="${i#*=}";
shift;
;;
-*|--*)
echo "Unknown option $i"
exit 1
;;
*)
;;
esac
done
fi
fi
# Get current timestamp and set at TAG
timestamp=$(date +%s)
# Make build folder if not already exists
mkdir -p ./build
# Check if logo.png exists, if not create
FILE=./logo.png
if [ -f "$FILE" ];
then
echo "$FILE exists. Using file in build";
else
echo "$FILE does not exist. Creating file";
cp ./default_logo.png ./logo.png;
fi
if [ "$CMD" == "local" ];
then
echo "Building from local git repo"
# Get current version from git tags
version=$(git describe --tags)
# Set docker image name
if [ "$OUTPUT_FORMAT" == "image" ];
then DockerImage="boringproxy-$GOOS-$GOARCH";
else DockerImage="boringproxy-$GOOS-$GOARCH:$timestamp";
fi
# Build docker image(s)
docker build -t $DockerImage . \
--build-arg VERSION=$(git describe --tags) \
--build-arg GOARCH=$GOARCH \
--build-arg GOOS=$GOOS;
fi
if [ "$CMD" == "remote" ];
then
echo "Building from remote git repo"
# Set docker image name
if [ "$OUTPUT_FORMAT" == "image" ];
then DockerImage="$GITHUB_USER.$BRANCH.boringproxy-$GOOS-$GOARCH";
else DockerImage="$GITHUB_USER.$BRANCH.boringproxy-$GOOS-$GOARCH:$timestamp";
fi
# Build docker image(s)
REPO="https://github.com/$GITHUB_USER/boringproxy.git"
docker build -t $DockerImage . \
--build-arg VERSION="$GITHUB_USER:$BRANCH" \
--build-arg GOARCH=$GOARCH \
--build-arg GOOS=$GOOS \
--build-arg BRANCH=$BRANCH \
--build-arg REPO=$REPO;
fi
# if DockerImage is set, continue
if [ -n "$DockerImage" ];
then
if [ "$OUTPUT_FORMAT" == "image" ];
then
# Prune intermediate images
docker image prune -f --filter label=boringproxy=builder
echo
echo "Docker file created with filename: $DockerImage"
echo "Use $DockerImage as image name when uploading"
else
# Prune intermediate images
docker image prune -f --filter label=boringproxy=builder
# Set filename for exec
if [ "$CMD" == "local" ];
then FILENAME="boringproxy-$GOOS-$GOARCH";
else FILENAME="$GITHUB_USER.$BRANCH.boringproxy-$GOOS-$GOARCH";
fi
# Copy exec from image
docker cp $(docker create $DockerImage):/boringproxy ./build/$FILENAME;
# Remove temp container
docker rm $(docker container ls -n 1 | awk '{ print $1 }' | grep -v CONTAINER)
# Remove image
docker rmi $DockerImage;
fi
fi

View File

@ -2,7 +2,7 @@
version=$(git describe --tags)
./scripts/generate_logo.sh
cp default_logo.png logo.png
cd ./cmd/boringproxy

32
scripts/upload_docker_github.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# This file is used to upload a build docker image to GitHub.
# Run build_docker.sh first to create new image
# Run from root boringproxy folder and call with ./scripts/upload_docker_image.sh github-username
# github-username must be lowercase
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
if [ -z "$1" ];
then {
echo "Container name required";
exit;
}
fi
if [ -z "$2" ];
then echo "GitHub username required";
else {
if [ -z "$3" ];
then {
echo "No TAG set, using latest";
tag='latest';
}
else tag=$3;
fi
docker image tag $1 ghcr.io/$2/$1:$tag
CR_PAT=`cat ~/.auth_tokens/github`
echo $CR_PAT | docker login ghcr.io -u $2 --password-stdin
docker push ghcr.io/$2/$1:$tag
} fi

View File

@ -5,11 +5,11 @@
<div class='list-item'>
{{ if eq $tokenData.Client "" }}
<span class='token'>{{$token}} (Owner: {{$tokenData.Owner}}) (Client: Any)</span>
<a href='/login?access_token={{$token}}'>Login link</a>
<img class='qr-code' src='{{index $.QrCodes $token}}' width=100 height=100>
{{ else }}
<span class='token'>{{$token}} (Owner: {{$tokenData.Owner}}) (Client: {{$tokenData.Client}})</span>
{{ end }}
<a href='/login?access_token={{$token}}'>Login link</a>
<img class='qr-code' src='{{index $.QrCodes $token}}' width=100 height=100>
<a href="/confirm-delete-token?token={{$token}}">
<button class='button'>Delete</button>
</a>