Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: minor fixes; consistenecy #66

Merged
merged 9 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions Dockerfile.tor-daemon
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,3 @@ ARG TOR_VERSION="0.4.8.7"
ARG TOR_IMAGE="quay.io/bugfest/tor"

FROM ${TOR_IMAGE}:${TOR_VERSION} as tor

USER 0

WORKDIR /app
RUN chmod g+w /app

VOLUME /run/tor/service

USER 1001
6 changes: 4 additions & 2 deletions Dockerfile.tor-onionbalance-manager
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20 as builder
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20 as builder

WORKDIR /src

Expand All @@ -15,7 +15,7 @@ FROM docker.io/library/alpine:3.17.2

ARG OB_VERSION="0.2.2"

RUN apk add --update \
RUN apk add --no-cache --update \
git=2.38.5-r0 \
py3-cryptography=38.0.3-r1 \
py3-pip=22.3.1-r1 \
Expand All @@ -27,4 +27,6 @@ RUN apk add --update \
WORKDIR /app
COPY --from=builder /out/onionbalance-local-manager /app

USER 1001

ENTRYPOINT ["/app/onionbalance-local-manager"]
92 changes: 52 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,39 @@
[![Release Charts](https://github.com/bugfest/tor-controller/actions/workflows/release.yml/badge.svg)](https://github.com/bugfest/tor-controller/actions/workflows/release.yml)
[![pages-build-deployment](https://github.com/bugfest/tor-controller/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/bugfest/tor-controller/actions/workflows/pages/pages-build-deployment)

`Tor-controller` let you define Tor instances in your k8s using a set of provided custom manifests (`tor`, `onion`, `onionha`).
`Tor-controller` lets you define Tor instances in your k8s using a set of provided custom resource definitions (`tor`, `onion`, `onionha`).

Compatible architectures: `amd64`, `arm64`, `arm`

Usage examples:
- Deploy a Tor daemon that listen for socks connections so you can let your k8s applications fetch resources through the Tor network.
- Run a `bridge`, `relay` or `exit` node
- Expose your k8s service in Tor network as onion service.
- If you want HA you can expose it with an onion balancer (allowing you to run up to 10 onion virtual services behind a single `.onion` address)
- Enable metrics and visualize them via prometheus/grafana
Usage examples:

**NOTE**: This project started as an exercise to update `kragniz`'s https://github.com/kragniz/. This version is a complete reimplementation.
- Deploy a Tor daemon that listens for socks connections so you can let your k8s applications fetch resources through the Tor network.
- Run a `bridge`, `relay` or `exit` node
- Expose your k8s service in the Tor network as onion service.
- If you want HA you can expose it with an onion balancer (allowing you to run up to 10 onion virtual services behind a single `.onion` address)
- Enable metrics and visualize them via prometheus/grafana

**NOTE**: This project started as an exercise to update `kragniz`'s https://github.com/kragniz/. This version is a complete reimplementation.

# Quick start

```shell
$ helm repo add bugfest https://bugfest.github.io/tor-controller
```bash
helm repo add bugfest https://bugfest.github.io/tor-controller

$ helm repo update
helm repo update

$ helm upgrade \
helm upgrade \
--install \
--create-namespace \
--namespace tor-controller \
--namespace tor-controller-system \
tor-controller \
bugfest/tor-controller
```

Check [install section](#install) bellow for more information.

# Table of Contents

- [Quick start](#quick-start)
- [Table of Contents](#table-of-contents)
- [Changes](#changes)
Expand Down Expand Up @@ -106,7 +108,7 @@ Roadmap / TODO
--------------

- Tor daemon management via socket (e.g: config reload)
- Manage Tor Server fingerprinting (ed25519_master_id_secret_key, secret_id_key) and automatic family and nickname management
- Manage Tor Server fingerprinting (ed25519_master_id_secret_key, secret_id_key) and automatic family and nickname management
- Tor relays:
- Non exit: Bridge, Snowflake, Middle/Guard
- Exit relay: Tor Exit
Expand All @@ -118,18 +120,22 @@ Install

Using helm (recommended):

$ helm repo add bugfest https://bugfest.github.io/tor-controller
$ helm repo update
$ helm upgrade --install \
--create-namespace --namespace tor-controller \
tor-controller bugfest/tor-controller
```bash
helm repo add bugfest https://bugfest.github.io/tor-controller
helm repo update
helm upgrade --install \
--create-namespace --namespace tor-controller \
tor-controller bugfest/tor-controller
```

For namespaced deployments add `--set namespaced=true` to helm's command when deploying.
Check [charts/tor-controller/README.md](charts/tor-controller/README.md) for a full set of available options.

Install tor-controller directly using the manifest (cluster-scoped):

$ kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/install.yaml
```bash
kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/install.yaml
```

Resources
---------
Expand All @@ -141,34 +147,33 @@ Resources
| onionbalancedservices | onionha,oha,obs | tor.k8s.torproject.org/v1alpha2 | true | OnionBalancedService |
| projectconfigs | | config.k8s.torproject.org/v2 | true | ProjectConfig |


***Tor***: Tor instance you can use to route traffic to/thru Tor network

**OnionService**: Exposes a set of k8s services using as a Tor Hidden Service. By default it generates a random .onion address

**OnionBalancedService**: Exposes a set of k8s services using [Onionbalance](https://gitlab.torproject.org/tpo/onion-services/onionbalance.git). It creates multiple backends providing some sort of HA. Users connect to the OnionBalancedService address and the requests are managed by one of the registered backends.


How to
------

Some examples you can use to start using tor-controller in your cluster
Some examples you can use to start using tor-controller in your cluster

Quickstart with random onion address
------------------------------------

TLDR

```bash
$ kubectl apply -f hack/sample/full-example-private.yaml
kubectl apply -f hack/sample/full-example-private.yaml

$ kubectl get onion
kubectl get onion
```

Create some deployment to test against, in this example we'll deploy an echoserver. You can find the definition at [hack/sample/echoserver.yaml](hack/sample/echoserver.yaml):

Apply it:

$ kubectl apply -f hack/sample/echoserver.yaml
kubectl apply -f hack/sample/echoserver.yaml

For a fixed address, we need a private key. This should be kept safe, since
someone can impersonate your onion service if it is leaked. Tor-Controller will generate an Onion v3 key-pair for you (stored as a secret), unless it already exists
Expand All @@ -194,7 +199,7 @@ spec:

Apply it:

$ kubectl apply -f hack/sample/onionservice.yaml
kubectl apply -f hack/sample/onionservice.yaml

List active OnionServices:

Expand All @@ -209,12 +214,11 @@ example-onion-service cfoj4552cvq7fbge6k22qmkun3jl37oz273hndr7ktvoahnqg5kdnzqd
This service should now be accessible from any tor client,
for example [Tor Browser](https://www.torproject.org/projects/torbrowser.html.en):


Onion service versions
----------------------

The `spec.version` field specifies which onion protocol to use.
Only v3 is supported.
Only v3 is supported.

tor-controller defaults to using v3 if `spec.version` is not specified.

Expand Down Expand Up @@ -245,11 +249,12 @@ Bring your own secret

Set `spec.privateKeySecret.name` to specify an existing secret. If you don't set `spec.privateKeySecret.key`, the controller expects it to have the following keys:

* `onionAddress` (corresponds to is the `hostname` file usually created by Tor)
* `privateKeyFile` (corresponds to `hs_ed25519_secret_key` file in v3 onion addresses or `private_key` in v2 ones)
* `publicKeyFile` (corresponds to `hs_ed25519_public_key` file in v3 onion addresses or `public_key` in v2 ones)
- `onionAddress` (corresponds to is the `hostname` file usually created by Tor)
- `privateKeyFile` (corresponds to `hs_ed25519_secret_key` file in v3 onion addresses or `private_key` in v2 ones)
- `publicKeyFile` (corresponds to `hs_ed25519_public_key` file in v3 onion addresses or `public_key` in v2 ones)

You can create such a secret with the following command:

```bash
$ kubectl create secret generic my-full-onion-secret \
--from-file=privateKeyFile=hs_ed25519_secret_key \
Expand All @@ -258,6 +263,7 @@ $ kubectl create secret generic my-full-onion-secret \
```

Onion Service example referencing a Secret only by name:

```yaml
apiVersion: tor.k8s.torproject.org/v1alpha2
kind: OnionService
Expand All @@ -272,12 +278,14 @@ spec:
If you set `spec.privateKeySecret.key`, the controller expects it to point to a valid `hs_ed25519_secret_key` content.

Secret example:

```bash
$ kubectl create secret generic my-private-onion-secret \
--from-file=mykeyname=hs_ed25519_secret_key
```

Onion Service example referencing a Secret only by name:

```yaml
apiVersion: tor.k8s.torproject.org/v1alpha2
kind: OnionService
Expand Down Expand Up @@ -345,6 +353,7 @@ Specifying Tor network bridges
Prerequisite: bridges information. You can get `obfs4` bridges visiting https://bridges.torproject.org/bridges/?transport=obfs4

Tor daemon instance [example](./hack/sample/tor-custom-config-bridges.yaml). Set the `config` field with the following content:

1. Enable bridges adding the line `UseBridges 1`
2. Place your bridges configuration

Expand Down Expand Up @@ -408,7 +417,6 @@ spec:
| `spec.topologySpreadConstraints` | Add [Topology Spread Constraints](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/). |
| `resources` | Set [Resource Requirements](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container) for the running containers. |


OnionBalancedService Pod Template
---------------------------------

Expand Down Expand Up @@ -511,7 +519,7 @@ spec:

Apply it:

$ kubectl apply -f hack/sample/onionbalancedservice.yaml
kubectl apply -f hack/sample/onionbalancedservice.yaml

List the frontend onion:

Expand All @@ -537,7 +545,7 @@ Tor Instances

(Available since v0.6.1)

Create a Tor instance, e.g: [hack/sample/tor.yaml](hack/sample/tor.yaml).
Create a Tor instance, e.g: [hack/sample/tor.yaml](hack/sample/tor.yaml).

```
apiVersion: tor.k8s.torproject.org/v1alpha2
Expand All @@ -550,7 +558,7 @@ metadata:

Apply it:

$ kubectl apply -f hack/sample/tor.yaml
kubectl apply -f hack/sample/tor.yaml

List the tor instances:

Expand All @@ -561,6 +569,7 @@ example-tor-instance 45m
```

Use it with socks via service:

```bash
$ kubectl run -ti curl --image=curlimages/curl:latest --restart=Never --rm -- -v -x socks://example-tor-instance-tor-svc:9050 ipinfo.io/ip
If you don't see a command prompt, try pressing enter.
Expand All @@ -577,10 +586,10 @@ Other examples:

- Use `spec.config` to add your customized configuration (Example: [hack/sample/tor-custom-config.yaml](hack/sample/tor-custom-config.yaml)).

- Set `spec.control.enable` to `true` to enable Tor's control port. If you don't set `spec.control.secret` or `spec.control.secretRef` a random password will be set and stored in a secret object. Example: [hack/sample/tor-custom-config.yaml](hack/sample/tor-external-full.yaml). In this example, the generated password can be retrieved with:
- Set `spec.control.enable` to `true` to enable Tor's control port. If you don't set `spec.control.secret` or `spec.control.secretRef` a random password will be set and stored in a secret object. Example: [hack/sample/tor-custom-config.yaml](hack/sample/tor-external-full.yaml). In this example, the generated password can be retrieved with:

```shell
echo $(kubectl get secret/example-tor-instance-full-tor-secret -o jsonpath='{.data.control}' | base64 -d)
```bash
echo $(kubectl get secret/example-tor-instance-full-tor-secret -o jsonpath='{.data.control}' | base64 -d)
```

Service Monitors
Expand Down Expand Up @@ -612,7 +621,6 @@ more information about onion services.

HA Hidden Services are implemented by [OnionBalance](https://gitlab.torproject.org/tpo/onion-services/onionbalance). Implements round-robin like load balancing on top of Tor onion services. A typical Onionbalance deployment will incorporate one frontend servers and multiple backend instances.` https://onionbalance.readthedocs.io/en/latest/v3/tutorial-v3.html


# How it works

tor-controller creates the following resources for each OnionService:
Expand All @@ -635,6 +643,7 @@ Builds
| tor | image | https://quay.io/repository/bugfest/tor | |

Dependencies:

- tor-daemon-manager Dockerfile uses bugfest/tor image (built from source). It is built in a separate project to speed up the compilation: [https://github.com/bugfest/tor-docker](https://github.com/bugfest/tor-docker)

Versions
Expand Down Expand Up @@ -662,14 +671,17 @@ References
----------

## Documentation

- Tor man pages: https://manpages.debian.org/testing/tor/tor.1.en.html
- Onionbalance: https://gitlab.torproject.org/tpo/onion-services/onionbalance
- Onionbalance tutorial: https://onionbalance.readthedocs.io/en/latest/v3/tutorial-v3.html
- Obfs4 pluggable transport: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/obfs4

## Utils

- Helm docs updated with https://github.com/norwoodj/helm-docs

## Other projects

- https://github.com/rdkr/oniongen-go
- https://github.com/ajvb/awesome-tor
2 changes: 1 addition & 1 deletion agents/tor/local/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (manager *Manager) Run() error {
defer cancel()
manager.daemon.SetContext(ctx)

err := os.Chmod("/run/tor/service", defaultUnixPermission)
err := os.Chmod("/run/tor/service", 0o700)
if err != nil {
log.Error(err, "error changing /run/tor/service permissions")
}
Expand Down
8 changes: 4 additions & 4 deletions charts/tor-controller/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
1. Check the tor-controller is running

$ kubectl -n {{ .Release.Namespace }} get po -l app.kubernetes.io/name={{ include "tor-controller.name" . }}
kubectl -n {{ .Release.Namespace }} get po -l app.kubernetes.io/name={{ include "tor-controller.name" . }}

2. Create a service

$ kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/sample/echoserver.yaml
kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/sample/echoserver.yaml

3. Expose it as a Tor hidden service (.onion) creating an onionservice object:

$ kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/sample/onionservice.yaml
kubectl apply -f https://raw.githubusercontent.com/bugfest/tor-controller/master/hack/sample/onionservice.yaml

4. Get the onion address and use your favourite tor browser to see your service running

$ kubectl get onionservice/example-onion-service -o {{`template='{{printf "%s\n" .status.hostname}}'`}}
kubectl get onionservice/example-onion-service -o {{`template='{{printf "%s\n" .status.hostname}}'`}}

8 changes: 4 additions & 4 deletions charts/tor-controller/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ podSecurityContext:

securityContext:
allowPrivilegeEscalation: false
# capabilities:
# drop:
# - ALL
capabilities:
drop:
- ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
runAsNonRoot: true
# runAsUser: 1000

service:
Expand Down
Loading