add system service

This commit is contained in:
AJ ONeal 2020-11-05 15:07:01 -07:00
parent 5deeab6fe2
commit 1635cbad9b
9 changed files with 142 additions and 22 deletions

View File

@ -34,6 +34,7 @@ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -mod vendor -ldflags "-H window
``` ```
The binary can be built with `VENDOR_ID` and `CLIENT_SECRET` built into the binary. The binary can be built with `VENDOR_ID` and `CLIENT_SECRET` built into the binary.
You can also change the `serviceName` and `serviceDescription` at build time.
See `examples/run-as-client.sh`. See `examples/run-as-client.sh`.
### Configure ### Configure

View File

@ -22,6 +22,7 @@ import (
"git.rootprojects.org/root/telebit/dbg" "git.rootprojects.org/root/telebit/dbg"
tbDns01 "git.rootprojects.org/root/telebit/internal/dns01" tbDns01 "git.rootprojects.org/root/telebit/internal/dns01"
"git.rootprojects.org/root/telebit/internal/http01" "git.rootprojects.org/root/telebit/internal/http01"
"git.rootprojects.org/root/telebit/internal/service"
"git.rootprojects.org/root/telebit/iplist" "git.rootprojects.org/root/telebit/iplist"
"git.rootprojects.org/root/telebit/mgmt" "git.rootprojects.org/root/telebit/mgmt"
"git.rootprojects.org/root/telebit/mgmt/authstore" "git.rootprojects.org/root/telebit/mgmt/authstore"
@ -61,8 +62,15 @@ var (
GitVersion = "v0.0.0-pre0+0000000" GitVersion = "v0.0.0-pre0+0000000"
// GitTimestamp refers to the timestamp of the most recent commit // GitTimestamp refers to the timestamp of the most recent commit
GitTimestamp = "0000-00-00T00:00:00+0000" GitTimestamp = "0000-00-00T00:00:00+0000"
// serviceName is the service name
serviceName = "telebit"
// serviceDesc
serviceDesc = "securely relay traffic through telebit.io"
) )
// Forward describes how to route a network connection
type Forward struct { type Forward struct {
scheme string scheme string
pattern string pattern string
@ -81,6 +89,23 @@ var VendorID string
var ClientSecret string var ClientSecret string
func main() { func main() {
if len(os.Args) >= 2 {
if "version" == strings.TrimLeft(os.Args[1], "-") {
fmt.Printf("telebit %s (%s) %s\n", GitVersion, GitRev[:7], GitTimestamp)
os.Exit(exitOk)
return
}
}
if len(os.Args) >= 2 {
if "install" == os.Args[1] {
if err := service.Install(); nil != err {
fmt.Fprintf(os.Stderr, "%v", err)
}
return
}
}
var domains []string var domains []string
var forwards []Forward var forwards []Forward
var portForwards []Forward var portForwards []Forward
@ -126,13 +151,6 @@ func main() {
) )
} }
if len(os.Args) >= 2 {
if "version" == os.Args[1] {
fmt.Printf("telebit %s %s %s\n", GitVersion, GitRev[:7], GitTimestamp)
os.Exit(exitOk)
}
}
if len(*acmeDirectory) > 0 { if len(*acmeDirectory) > 0 {
if *acmeStaging { if *acmeStaging {
fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n") fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n")
@ -829,19 +847,6 @@ func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {
return provider, nil return provider, nil
} }
type ACMEProvider struct {
BaseURL string
provider challenge.Provider
}
func (p *ACMEProvider) Present(domain, token, keyAuth string) error {
return p.provider.Present(domain, token, keyAuth)
}
func (p *ACMEProvider) CleanUp(domain, token, keyAuth string) error {
return p.provider.CleanUp(domain, token, keyAuth)
}
// newDuckDNSProvider is for the sake of demoing the tunnel // newDuckDNSProvider is for the sake of demoing the tunnel
func newDuckDNSProvider(token string) (*duckdns.DNSProvider, error) { func newDuckDNSProvider(token string) (*duckdns.DNSProvider, error) {
config := duckdns.NewDefaultConfig() config := duckdns.NewDefaultConfig()

View File

@ -9,7 +9,7 @@ source .env
VENDOR_ID="${VENDOR_ID:-"${VENDOR_ID:-"test-id"}"}" VENDOR_ID="${VENDOR_ID:-"${VENDOR_ID:-"test-id"}"}"
CLIENT_SECRET="${CLIENT_SECRET:-}" CLIENT_SECRET="${CLIENT_SECRET:-}"
#go build -mod=vendor -o ./telebit \ #go build -mod=vendor -o ./telebit \
# -ldflags="-X 'main.VendorID=$VENDOR_ID' -X 'main.ClientSecret=$CLIENT_SECRET'" \ # -ldflags="-X 'main.VendorID=$VENDOR_ID' -X 'main.ClientSecret=$CLIENT_SECRET' -X 'main.serviceName=telebit' -X 'main.serviceDesc=securely tunnel through telebit.io'" \
# cmd/telebit/*.go # cmd/telebit/*.go
go build -mod=vendor -o telebit \ go build -mod=vendor -o telebit \
cmd/telebit/*.go cmd/telebit/*.go

2
go.mod
View File

@ -21,7 +21,7 @@ require (
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
golang.org/x/text v0.3.3 // indirect golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect

View File

@ -0,0 +1,10 @@
package service
import (
"errors"
)
// Install ensures a systemd service is active
func Install() error {
return errors.New("'install' not supported for system services on this platform")
}

12
internal/service/other.go Normal file
View File

@ -0,0 +1,12 @@
// +build !darwin,!linux,!windows
package service
import (
"errors"
)
// Install ensures a windows service is active
func Install() error {
return errors.New("not supported for system services on this platform")
}

View File

@ -0,0 +1,79 @@
package service
import (
"errors"
"fmt"
"os"
"path/filepath"
"golang.org/x/sys/windows/svc/eventlog"
"golang.org/x/sys/windows/svc/mgr"
)
// Install ensures a windows service is active
func Install(name, desc string) error {
exepath, err := getExecPath(os.Args[0])
if err != nil {
return err
}
return installService(name, desc, exepath)
}
func getExecPath(exepath string) (string, error) {
p, err := filepath.Abs(exepath)
if err != nil {
return "", err
}
fi, err := os.Stat(p)
if err == nil {
if fi.Mode().IsRegular() {
return p, nil
}
}
if 0 == len(filepath.Ext(p)) {
var err error
p += ".exe"
fi, err = os.Stat(p)
if nil != err {
return err
}
}
if !fi.Mode().IsRegular() {
// this should never happen
return "", errors.New("not a regular file")
}
return p, nil
}
func install(name, desc, exepath string) error {
m, err := mgr.Connect()
if nil != err {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if nil == err {
s.Close()
return nil
}
s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: desc}, "is", "auto-started")
if err != nil {
return err
}
defer s.Close()
err = eventlog.InstallAsEventCreate(name, eventlog.Error|eventlog.Warning|eventlog.Info)
if nil != err {
s.Delete()
return fmt.Errorf("could not install system service: %v", err)
}
return nil
}

View File

@ -0,0 +1,10 @@
package service
import (
"errors"
)
// Install ensures a systemd service is active
func Install() error {
return errors.New("'install' not supported for system services on this platform")
}

3
vendor/modules.txt vendored
View File

@ -162,6 +162,9 @@ golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
golang.org/x/sys/windows/registry golang.org/x/sys/windows/registry
golang.org/x/sys/windows/svc
golang.org/x/sys/windows/svc/eventlog
golang.org/x/sys/windows/svc/mgr
# golang.org/x/text v0.3.3 # golang.org/x/text v0.3.3
## explicit ## explicit
golang.org/x/text/secure/bidirule golang.org/x/text/secure/bidirule