Testing invite system - current state

I could get the invite system working. I will explain how and open TOODs

backend / menshen

    go run ./cmd/menshen/main.go \
            --verbose \
            --from-eip-file /home/pea/projects/leap/jnk/quickstart/menshen/eip-service.json \
            --client-cert-url https://api.black.riseup.net:4430/3/cert \
            --ca-file riseup-ca.pem \
            --from-provider-json-file riseup-provider.json \
            --db-file /home/pea/projects/leap/jnk/quickstart/menshen/menshen.db
}

I used main branch of menshen repo. Constraints/requirements:

  • only a single location for gateways is used AND
  • only private gateways are used

This is my inventory. It has two VPN gateways in Seattle. Both are private (assigned to bucket1). You can use an unlimited number of gateways.

{
  "gateways": [
    {
      "capabilities": {
        "adblock": false,
        "filter_dns": false,
        "limited": false,
        "transport": [
          {
            "ports": [
              "80",
              "1194"
            ],
            "protocols": [
              "tcp",
              "udp"
            ],
            "type": "openvpn"
          },
          {
            "options": {
              "cert": "/ntRNI6JYP7R6kGKldibKWj0aCsv96Hdu/jSGncPy+rcverCLI7Emod+vRkz61hM7F/udA",
              "iatMode": "0"
            },
            "ports": [
              "443"
            ],
            "protocols": [
              "tcp"
            ],
            "type": "obfs4"
          }
        ]
      },
      "host": "vpn01-sea.riseup.net",
      "ip_address": "204.13.164.252",
      "location": "Seattle",
      "bucket": "bucket1"
    },
    {
      "capabilities": {
        "adblock": false,
        "filter_dns": false,
        "limited": false,
        "transport": [
          {
            "ports": [
              "80",
              "1194"
            ],
            "protocols": [
              "tcp",
              "udp"
            ],
            "type": "openvpn"
          },
          {
            "options": {
              "cert": "/ntRNI6JYP7R6kGKldibKWj0aCsv96Hdu/jSGncPy+rcverCLI7Emod+vRkz61hM7F/udA",
              "iatMode": "0"
            },
            "ports": [
              "443"
            ],
            "protocols": [
              "tcp"
            ],
            "type": "obfs4"
          }
        ]
      },
      "host": "vpn15-sea.riseup.net",
      "ip_address": "199.254.238.55",
      "location": "Seattle",
      "bucket": "bucket1"
    }
  ],
  "locations": {
    "Seattle": {
      "country_code": "US",
      "hemisphere": "N",
      "name": "Seattle",
      "timezone": "-7"
    }
  },
  "openvpn_configuration": {
    "auth": "SHA512",
    "cipher": "AES-256-GCM",
    "data-ciphers": "AES-256-GCM",
    "dev": "tun",
    "float": "",
    "keepalive": "10 30",
    "key-direction": "1",
    "nobind": true,
    "persist-key": true,
    "rcvbuf": "0",
    "sndbuf": "0",
    "tls-cipher": "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
    "tls-version-min": "1.2",
    "verb": "3"
  },
  "serial": 3,
  "version": 3
}

Desktop

I'm using fix-920-followup branch. I has some fixes after recent bitmask-core changes. Additionally I use a go.work and use my local bitmask-core repo. This is my go.work:

go 1.22.2

use (
    .
    ../bitmask-core
)

bitmask-core

I checkout branch fix-37. It updates the kcp module. Without the kcp modules of obsvpn and bitmask-core are not compatible. This will crash the obsvpn backend. I created an issue for that: obfsvpn#70

obsvpn

I'm using main branch.

go run ./cmd/server \
    --addr 127.0.0.1 \
    --port 4430 \
    --remote "127.0.0.1:8443" \
    --state $(pwd)/state \
    -v \

This is the state/* content:

# obfs4 torrc client bridge line
#
# This file is an automatically generated bridge line based on
# the current obfs4proxy configuration.  EDITING IT WILL HAVE
# NO EFFECT.
#
# Before distributing this Bridge, edit the placeholder fields
# to contain the actual values:
#  <IP ADDRESS>  - The public IP address of your obfs4 bridge.
#  <PORT>        - The TCP/IP port of your obfs4 bridge.
#  <FINGERPRINT> - The bridge's fingerprint.

Bridge obfs4 <IP ADDRESS>:<PORT> <FINGERPRINT> cert=sAaLYTa6kzJp+/LNY6Zqk8uj5DKpmMx1ROzUHOAOuZxLSEAkLk7WoC1BK86sTOTIzvEaMg iat-mode=0
{"node-id":"b0068b6136ba933269fbf2cd63a66a93cba3e432","private-key":"d1fb5dc47c147f9c861eaaf696211066d9ae004cbd5895824b83ea07e33b6e73","public-key":"","drbg-seed":"35b7af78bba720d093131e39693507819ca8afb243031b2e0000000000000000","iat-mode":0}

When I run the introducer proxy and stop it, it throws a lot of errors. You know what I mean when you have uesd it in the past :). This should be fixed. I don't know if there is already an issue.

DEBUG 2025/01/22 17:54:41 error accepting connecti^CDEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection
DEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection
DEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection
DEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection
DEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection
DEBUG 2025/01/22 17:54:41 error accepting connection: accept tcp 127.0.0.1:4430: use of closed network connection

Generate an invite token

pea@peabox:menshen ./invitectl --db /home/pea/projects/leap/jnk/quickstart/menshen/menshen.db new --buckets bucket1 --invite-code-parameter cmd/invitectl/parameters.yml --debug
...

parameters.yml

pea@peabox:pkg cat /home/pea/projects/leap/menshen/cmd/invitectl/parameters.yml
type: obfsvpnintro
addr: localhost:4430
cert: take the one from above
fqdn: localhost
kcp: false

Running the desktop client

I used the following envs:

export LOG_LEVEL=TRACE
export API_VERSION=5
export API_URL="http://localhost:8443"
export LEAP_INTRODUCER_URL="obfsvpnintro://localhost:4430/?cert=sAaLYTa6kzJp%2B%2FLNY6Zqk8uj5DKpmMx1ROzUHOAOuZxLSEAkLk7WoC1BK86sTOTIzvEaMg&fqdn=localhost&kcp=0&auth=solitech_J3BhkafGwb7dePoZF31rKg%3D%3D"

I built the riseup branded client.

NOTES

  • I have not tested the Android client
  • I have not tested bridges. This is an open TODO for the next days
  • When adding a new introducer, the old one should be deleted (by fqdn). This sometimes? does not work. Sometimes helps to delete ~/.config/bitmask/bitmask.db if the auth token is not sent. you can use sudo ngrep -d any -W byline -q port 8443 to test
  • With this inventory menshen could not be used without invite tokens. menshen returns an empty list of gateways and the client does not really know what to do.

GATEWAY SELECTION

  • menshen selects randomly one gateway and returns all protocols/endpoints for this endpoint as own gateways (internally it used VPNEndpoints and not gateways)
  • so before (v3) we returned a list of gateways. And each gateway had a list of protocols/ports
  • Currently, we return gateway1+tpc+80, gateway1+udp+80, gateway1+udp+443, ... (but always gateway1)
  • In the end, we end up calling openvpn with these arguments using the Desktop:

--remote 204.13.164.252 1194 tcp4 --remote 204.13.164.252 80 tcp4 --remote 204.13.164.252 80 tcp4

Summary

It works, but some open MRs need to be merged.

cc @mcnair @cyberta

Edited by Pea Nut