diff --git a/boringproxy.go b/boringproxy.go index c6dec80..ab4955c 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "flag" "fmt" - "github.com/caddyserver/certmagic" "io" "log" "net" @@ -14,6 +13,8 @@ import ( "strings" "sync" "time" + + "github.com/caddyserver/certmagic" ) type Config struct { @@ -40,13 +41,18 @@ func Listen() { adminDomain := flagSet.String("admin-domain", "", "Admin Domain") sshServerPort := flagSet.Int("ssh-server-port", 22, "SSH Server Port") certDir := flagSet.String("cert-dir", "", "TLS cert directory") - flagSet.Parse(os.Args[2:]) + err := flagSet.Parse(os.Args[2:]) + if err != nil { + fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err) + } + + log.Println("Starting up") webUiDomain := *adminDomain if *adminDomain == "" { reader := bufio.NewReader(os.Stdin) - log.Print("Enter Admin Domain: ") + fmt.Print("Enter Admin Domain: ") text, _ := reader.ReadString('\n') webUiDomain = strings.TrimSpace(text) } @@ -64,7 +70,7 @@ func Listen() { //certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA certConfig := certmagic.NewDefault() - err := certConfig.ManageSync([]string{config.WebUiDomain}) + err = certConfig.ManageSync([]string{config.WebUiDomain}) if err != nil { log.Fatal(err) } diff --git a/client.go b/client.go index 1858bd1..c1a8471 100644 --- a/client.go +++ b/client.go @@ -6,8 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/caddyserver/certmagic" - "golang.org/x/crypto/ssh" "io" "io/ioutil" "log" @@ -16,6 +14,9 @@ import ( "strings" "sync" "time" + + "github.com/caddyserver/certmagic" + "golang.org/x/crypto/ssh" ) type Client struct { diff --git a/cmd/boringproxy/main.go b/cmd/boringproxy/main.go index 7f21c6d..5746857 100644 --- a/cmd/boringproxy/main.go +++ b/cmd/boringproxy/main.go @@ -3,28 +3,36 @@ package main import ( "flag" "fmt" - "github.com/boringproxy/boringproxy" - "log" "os" + + "github.com/boringproxy/boringproxy" ) -func main() { +const usage = `Usage: %s [command] [flags] +Commands: + server Start a new server. + client Connect to a server. + +Use "%[1]s command -h" for a list of flags for the command. +` + +func main() { if len(os.Args) < 2 { - fmt.Println("Invalid arguments") + fmt.Fprintln(os.Stderr, os.Args[0]+": Need a command") + fmt.Printf(usage, os.Args[0]) os.Exit(1) } command := os.Args[1] switch command { + case "help", "-h", "--help", "-help": + fmt.Printf(usage, os.Args[0]) case "server": - log.Println("Starting up") boringproxy.Listen() - case "client": - - flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError) + flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError) server := flagSet.String("server", "", "boringproxy server") token := flagSet.String("token", "", "Access token") name := flagSet.String("client-name", "", "Client name") @@ -32,7 +40,11 @@ func main() { certDir := flagSet.String("cert-dir", "", "TLS cert directory") acmeEmail := flagSet.String("acme-email", "", "Email for ACME (ie Let's Encrypt)") dnsServer := flagSet.String("dns-server", "", "Custom DNS server") - flagSet.Parse(os.Args[2:]) + + err := flagSet.Parse(os.Args[2:]) + if err != nil { + fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err) + } config := &boringproxy.ClientConfig{ ServerAddr: *server, @@ -47,7 +59,7 @@ func main() { client := boringproxy.NewClient(config) client.RunPuppetClient() default: - fmt.Println("Invalid command " + command) + fmt.Fprintln(os.Stderr, os.Args[0]+": Invalid command "+command) os.Exit(1) } } diff --git a/docs/systemd.md b/docs/systemd.md new file mode 100644 index 0000000..50386c8 --- /dev/null +++ b/docs/systemd.md @@ -0,0 +1,87 @@ +# Systemd Integration + +These instructions assume that you have followed the [Installation instruction](https://boringproxy.io/#installation) and installed the boringproxy binary to `/usr/local/bin/` + +If you install the binary to a different path you will need to update the path in the service files. + +--- + +## System User and WorkingDirectory Setup + +The following steps setup a user and working directory for boringproxy to match with standard best practices as not running processes as the root user. + +### Admin Server & Client Setup +Currently the boringproxy client does not need + +```bash +# create the system user - We are using a system user as we don't want regular user permissions assigned since all it is going to be doing is running boringproxy for us. We also specify the shell as /bin/false so that nothing can login as this user just incase. +sudo useradd -d /opt/boringproxy -m --system --shell /bin/false boringproxy + +# Since the boringproxy working directory houses data that we dont want to be exposed to other services/users are all we will make it so that ony the boringproxy user itself us able to access files and directories in the working directory +sudo chmod 700 /opt/boringproxy +``` + +## boringproxy Server Service + +Download the boringproxy-server.service file +```bash +# with wget +wget https://raw.githubusercontent.com/boringproxy/boringproxy/master/systemd/boringproxy-server.service -O /tmp/boringproxy-server.service + +# or with curl +curl https://raw.githubusercontent.com/boringproxy/boringproxy/master/systemd/boringproxy-server.service --output /tmp/boringproxy-server.service + +# move the systemd file into the correct location +sudo mv /tmp/boringproxy-server.service /etc/systemd/system/boringproxy-server.service +``` + + +Edit `/etc/systemd/system/boringproxy-server.service` and replace the admin domain `bp.example.com` with the domain that the server will be available at. EX: `-admin-domain proxy.bpuser.me` + +Enable and start the boringproxy server service with the following command +```bash +sudo systemctl enable --now boringproxy-server.service +``` + +This will make sure that boringproxy server will always start backup if the host is restarted. + +--- + +## boringproxy Client Service + +Download the boringproxy-client@.service file +```bash +# with wget +wget https://raw.githubusercontent.com/boringproxy/boringproxy/master/systemd/boringproxy-client%40.service -O "/tmp/boringproxy-client@.service" + +# or with curl +curl https://raw.githubusercontent.com/boringproxy/boringproxy/master/systemd/boringproxy-client%40.service --output "/tmp/boringproxy-client@.service" + +sudo mv /tmp/boringproxy-client@.service /etc/systemd/system/boringproxy-client@.service +``` + +Edit `/etc/systemd/system/boringproxy-client@.service` and replace the server address `bp.example.com` with the domain that the server is located at. EX: `-server proxy.bpuser.me` + +also edit the token value `your-bp-server-token` with the token from when you installed the server. EX: `-token rt42g.......3fn` + +Enable and start the boringproxy server service with the following command +```bash +# the value after the @ symbol in the service name is what will determine the name of the client in the Admin UI +sudo systemctl enable --now boringproxy-client@default.service +``` + +This will make sure that boringproxy client will always start backup and reconnect to the boringclient server if the host is restarted or goes down for some reason. + +## Notes +### Updating an existing boringproxy Server instance +If you have already ran the admin server you will need to migrate the db and change its permissions to keep your existing settings. + +```bash +sudo mv /root/boringproxy_db.json /opt/boringproxy/boringproxy_db.json +sudo chown boringproxy:boringproxy /opt/boringproxy/boringproxy_db.json +``` + +### Client Service Unit File +This systemd service file is a template service which allows you to spawn multiple clients with a specified name. + +If you do not need/want the ability to launch multiple clients with a single service file and do not want to have to specify `boringproxy-client@.service` when interacting with the service, rename the service file to `boringproxy-client.service` and remove the `%I` from the `Description` field and replace the `%i` after `-client-name` with the name you want the client to have. after those modifications you can use the service as `boringproxy-client.service` \ No newline at end of file diff --git a/systemd/boringproxy-client@.service b/systemd/boringproxy-client@.service new file mode 100644 index 0000000..712b962 --- /dev/null +++ b/systemd/boringproxy-client@.service @@ -0,0 +1,14 @@ +[Unit] +Description=boringproxy client (%I) +After=network.target + +[Service] +PrivateTmp=true +Type=simple +User=boringproxy +Group=boringproxy +WorkingDirectory=/opt/boringproxy/ +ExecStart=/usr/local/bin/boringproxy client -server bp.example.com -token your-bp-server-token -client-name %i + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/systemd/boringproxy-server.service b/systemd/boringproxy-server.service new file mode 100644 index 0000000..360c511 --- /dev/null +++ b/systemd/boringproxy-server.service @@ -0,0 +1,14 @@ +[Unit] +Description=boringproxy Admin Server +After=network.target + +[Service] +PrivateTmp=true +Type=simple +User=boringproxy +Group=boringproxy +WorkingDirectory=/opt/boringproxy/ +ExecStart=/usr/local/bin/boringproxy server -admin-domain bp.example.com + +[Install] +WantedBy=multi-user.target