Skip to content

Commit

Permalink
More refactoring and updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniomika committed May 2, 2020
1 parent 17dcaad commit d5af803
Show file tree
Hide file tree
Showing 19 changed files with 534 additions and 491 deletions.
6 changes: 5 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/.git/
/keys/
/.github/
/.gitignore
/deploy/
/dist/
/sish
/.vscode/
28 changes: 14 additions & 14 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@
"program": "${workspaceFolder}",
"env": {},
"args": [
"-sish.auth=false",
"-sish.debug=true",
"-sish.subdomainlen=3",
"-sish.httpsenabled=false",
"-sish.http=localhost:8081",
"-sish.addr=localhost:2222",
"-sish.domain=testing.ssi.sh",
"-sish.forcerandomsubdomain=false",
"-sish.bindrandom=false",
"-sish.tcpalias=true",
"-sish.proxyprotoenabled=false",
"-sish.logtoclient=true",
"-sish.adminenabled=true",
"-sish.serviceconsoleenabled=true"
"--debug=true",
"--max-subdomain-length=3",
"--http-address=:8081",
"--ssh-address=:2222",
"--domain=testing.ssi.sh",
"--force-random-subdomain=false",
"--bind-random-ports=false",
"--enable-https=false",
"--enable-authentication=false",
"--enable-tcp-aliases=true",
"--enable-proxy-protocol=false",
"--enable-log-to-client=true",
"--enable-admin-console=true",
"--enable-service-console=true"
]
}
]
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ LABEL maintainer="Antonio Mika <me@antoniomika.me>"
WORKDIR /app

COPY --from=builder /tmp /tmp
COPY --from=builder /app/pubkeys /app/pubkeys
COPY --from=builder /app/deploy/pubkeys /app/deploy/pubkeys
COPY --from=builder /app/templates /app/templates
COPY --from=builder /go/bin/sish /app/sish

Expand Down
54 changes: 28 additions & 26 deletions cmd/sish.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package cmd
import (
"fmt"
"log"
"time"

"github.com/antoniomika/sish/sshmuxer"
"github.com/fsnotify/fsnotify"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -42,48 +44,49 @@ func init() {
rootCmd.SetVersionTemplate(fmt.Sprintf("Version: %v\nCommit: %v\nDate: %v\n", Version, Commit, Date))

rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "config.yml", "Config file")
rootCmd.PersistentFlags().StringP("ssh-addr", "a", "localhost:2222", "The address to listen for SSH connections")
rootCmd.PersistentFlags().StringP("http-addr", "i", "localhost:80", "The address to listen for HTTP connections")
rootCmd.PersistentFlags().StringP("https-addr", "t", "localhost:443", "The address to listen for HTTPS connections")

rootCmd.PersistentFlags().StringP("ssh-address", "a", "localhost:2222", "The address to listen for SSH connections")
rootCmd.PersistentFlags().StringP("http-address", "i", "localhost:80", "The address to listen for HTTP connections")
rootCmd.PersistentFlags().StringP("https-address", "t", "localhost:443", "The address to listen for HTTPS connections")
rootCmd.PersistentFlags().StringP("redirect-root-location", "r", "https://github.com/antoniomika/sish", "Where to redirect the root domain to")
rootCmd.PersistentFlags().StringP("cert-dir", "s", "ssl/", "The location of pem files for HTTPS (fullchain.pem and privkey.pem)")
rootCmd.PersistentFlags().StringP("certificate-directory", "s", "deploy/ssl/", "The location of pem files for HTTPS (fullchain.pem and privkey.pem)")
rootCmd.PersistentFlags().StringP("domain", "d", "ssi.sh", "The domain for HTTP(S) multiplexing")
rootCmd.PersistentFlags().StringP("banned-subdomains", "b", "localhost", "A comma separated list of banned subdomains")
rootCmd.PersistentFlags().StringP("banned-ips", "x", "", "A comma separated list of banned ips")
rootCmd.PersistentFlags().StringP("banned-countries", "o", "", "A comma separated list of banned countries")
rootCmd.PersistentFlags().StringP("whitelisted-ips", "w", "", "A comma separated list of whitelisted ips")
rootCmd.PersistentFlags().StringP("whitelisted-countries", "y", "", "A comma separated list of whitelisted countries")
rootCmd.PersistentFlags().StringP("privkey-passphrase", "p", "S3Cr3tP4$$phrAsE", "Passphrase to use for the server private key")
rootCmd.PersistentFlags().StringP("privkey-location", "l", "keys/ssh_key", "SSH server private key")
rootCmd.PersistentFlags().StringP("auth-password", "u", "S3Cr3tP4$$W0rD", "Password to use for password auth")
rootCmd.PersistentFlags().StringP("auth-keys-dir", "k", "pubkeys/", "Directory for public keys for pubkey auth")
rootCmd.PersistentFlags().StringP("bind-range", "n", "0,1024-65535", "Ports that are allowed to be bound")
rootCmd.PersistentFlags().StringP("private-key-passphrase", "p", "S3Cr3tP4$$phrAsE", "Passphrase to use for the server private key")
rootCmd.PersistentFlags().StringP("private-key-location", "l", "deploy/keys/ssh_key", "SSH server private key")
rootCmd.PersistentFlags().StringP("authentication-password", "u", "S3Cr3tP4$$W0rD", "Password to use for password auth")
rootCmd.PersistentFlags().StringP("authentication-keys-directory", "k", "deploy/pubkeys/", "Directory for public keys for pubkey auth")
rootCmd.PersistentFlags().StringP("port-bind-range", "n", "0,1024-65535", "Ports that are allowed to be bound")
rootCmd.PersistentFlags().StringP("proxy-protocol-version", "q", "1", "What version of the proxy protocol to use.\nCan either be 1, 2, or userdefined. If userdefined, the user needs to add a command to SSH called proxyproto:version (ie proxyproto:1)")
rootCmd.PersistentFlags().StringP("admin-token", "j", "S3Cr3tP4$$W0rD", "The token to use for admin access")
rootCmd.PersistentFlags().StringP("admin-console-token", "j", "S3Cr3tP4$$W0rD", "The token to use for admin access")
rootCmd.PersistentFlags().StringP("service-console-token", "m", "", "The token to use for service access. Auto generated if empty.")

rootCmd.PersistentFlags().BoolP("append-user-to-subdomain", "", false, "Whether or not to append the user to the subdomain")
rootCmd.PersistentFlags().BoolP("admin-enabled", "", false, "Whether or not to enable the admin console")
rootCmd.PersistentFlags().BoolP("service-console-enabled", "", false, "Whether or not to enable the admin console for each service and send the info to users")
rootCmd.PersistentFlags().BoolP("force-random-subdomain", "", true, "Whether or not to force a random subdomain")
rootCmd.PersistentFlags().BoolP("verify-origin", "", true, "Whether or not to verify origin on websocket connection")
rootCmd.PersistentFlags().BoolP("verify-ssl", "", true, "Whether or not to verify SSL on proxy connection")
rootCmd.PersistentFlags().BoolP("https-enabled", "", false, "Whether or not to listen for HTTPS connections")
rootCmd.PersistentFlags().BoolP("redirect-root", "", true, "Whether or not to redirect the root domain")
rootCmd.PersistentFlags().BoolP("use-geodb", "", false, "Whether or not to use the maxmind geodb")
rootCmd.PersistentFlags().BoolP("authentication-enabled", "", false, "Whether or not to require auth on the SSH service")
rootCmd.PersistentFlags().BoolP("cleanup-unbound", "", true, "Whether or not to cleanup unbound (forwarded) SSH connections")
rootCmd.PersistentFlags().BoolP("bind-random", "", true, "Bind ports randomly (OS chooses)")
rootCmd.PersistentFlags().BoolP("proxy-protocol-enabled", "", false, "Whether or not to enable the use of the proxy protocol")
rootCmd.PersistentFlags().BoolP("bind-random-ports", "", true, "Bind ports randomly (OS chooses)")
rootCmd.PersistentFlags().BoolP("append-user-to-subdomain", "", false, "Whether or not to append the user to the subdomain")
rootCmd.PersistentFlags().BoolP("debug", "", false, "Whether or not to print debug information")
rootCmd.PersistentFlags().BoolP("version", "", false, "Print version and exit")
rootCmd.PersistentFlags().BoolP("tcp-alias", "", false, "Whether or not to allow the use of TCP aliasing")
rootCmd.PersistentFlags().BoolP("log-to-client", "", false, "Whether or not to log http requests to the client")
rootCmd.PersistentFlags().BoolP("enable-geodb", "", false, "Whether or not to use the maxmind geodb")
rootCmd.PersistentFlags().BoolP("enable-authentication", "", false, "Whether or not to require auth on the SSH service")
rootCmd.PersistentFlags().BoolP("enable-proxy-protocol", "", false, "Whether or not to enable the use of the proxy protocol")
rootCmd.PersistentFlags().BoolP("enable-https", "", false, "Whether or not to listen for HTTPS connections")
rootCmd.PersistentFlags().BoolP("enable-redirect-root", "", true, "Whether or not to redirect the root domain")
rootCmd.PersistentFlags().BoolP("enable-admin-console", "", false, "Whether or not to enable the admin console")
rootCmd.PersistentFlags().BoolP("enable-service-console", "", false, "Whether or not to enable the admin console for each service and send the info to users")
rootCmd.PersistentFlags().BoolP("enable-tcp-aliases", "", false, "Whether or not to allow the use of TCP aliasing")
rootCmd.PersistentFlags().BoolP("enable-log-to-client", "", false, "Whether or not to log http requests to the client")

rootCmd.PersistentFlags().IntP("http-port-override", "", 0, "The port to use for http command output")
rootCmd.PersistentFlags().IntP("https-port-override", "", 0, "The port to use for https command output")
rootCmd.PersistentFlags().IntP("max-subdomain-len", "", 3, "The length of the random subdomain to generate")
rootCmd.PersistentFlags().IntP("connection-idle-timeout", "", 5, "Number of seconds to wait for activity before closing a connection")
rootCmd.PersistentFlags().IntP("max-subdomain-length", "", 3, "The length of the random subdomain to generate")

rootCmd.PersistentFlags().DurationP("connection-idle-timeout", "", 5*time.Second, "Number of seconds to wait for activity before closing a connection")
}

func initConfig() {
Expand Down Expand Up @@ -113,6 +116,5 @@ func Execute() error {
}

func runCommand(cmd *cobra.Command, args []string) {
// log.Printf("%+v", viper.AllSettings())
// log.Println(cmd, args)
sshmuxer.Start()
}
40 changes: 40 additions & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
admin-console-token: S3Cr3tP4$$W0rD
append-user-to-subdomain: false
authentication-keys-directory: deploy/pubkeys/
authentication-password: S3Cr3tP4$$W0rD
banned-countries: ""
banned-ips: ""
banned-subdomains: localhost
bind-random-ports: true
certificate-directory: deploy/ssl/
cleanup-unbound: true
config: config.yml
connection-idle-timeout: 5s
debug: false
domain: ssi.sh
enable-admin-console: false
enable-authentication: false
enable-geodb: false
enable-https: false
enable-log-to-client: false
enable-proxy-protocol: false
enable-redirect-root: true
enable-service-console: false
enable-tcp-aliases: false
force-random-subdomain: true
http-address: localhost:80
http-port-override: 0
https-address: localhost:443
https-port-override: 0
max-subdomain-length: 3
port-bind-range: 0,1024-65535
private-key-location: deploy/keys/ssh_key
private-key-passphrase: S3Cr3tP4$$phrAsE
proxy-protocol-version: "1"
redirect-root-location: https://github.com/antoniomika/sish
service-console-token: ""
ssh-address: localhost:2222
verify-origin: true
verify-ssl: true
whitelisted-countries: ""
whitelisted-ips: ""
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ require (
gopkg.in/ini.v1 v1.55.0 // indirect
)

go 1.13
go 1.14
53 changes: 24 additions & 29 deletions http.go → httpmuxer/httpmuxer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package httpmuxer

import (
"bytes"
Expand All @@ -16,23 +16,18 @@ import (
"strings"
"time"

"github.com/antoniomika/sish/utils"
"github.com/gorilla/websocket"
"github.com/koding/websocketproxy"
"github.com/spf13/viper"

"github.com/gin-gonic/gin"
)

// ProxyHolder holds proxy and connection info
type ProxyHolder struct {
ProxyHost string
ProxyTo string
Scheme string
SSHConn *SSHConnection
}

func startHTTPHandler(state *State) {
// StartHTTPHandler initializes the HTTP service
func StartHTTPHandler(state *utils.State) {
releaseMode := gin.ReleaseMode
if *debug {
if viper.GetBool("debug") {
releaseMode = gin.DebugMode
}
gin.SetMode(releaseMode)
Expand Down Expand Up @@ -62,12 +57,12 @@ func startHTTPHandler(state *State) {
param.Latency = param.Latency - param.Latency%time.Second
}

if *adminToken != "" && strings.Contains(param.Path, *adminToken) {
param.Path = strings.Replace(param.Path, *adminToken, "[REDACTED]", 1)
if viper.GetString("admin-console-token") != "" && strings.Contains(param.Path, viper.GetString("admin-console-token")) {
param.Path = strings.Replace(param.Path, viper.GetString("admin-console-token"), "[REDACTED]", 1)
}

if *serviceConsoleToken != "" && strings.Contains(param.Path, *serviceConsoleToken) {
param.Path = strings.Replace(param.Path, *serviceConsoleToken, "[REDACTED]", 1)
if viper.GetString("service-console-token") != "" && strings.Contains(param.Path, viper.GetString("service-console-token")) {
param.Path = strings.Replace(param.Path, viper.GetString("service-console-token"), "[REDACTED]", 1)
}

logLine := fmt.Sprintf("%v | %s |%s %3d %s| %13v | %15s |%s %-7s %s %s\n%s",
Expand All @@ -81,27 +76,27 @@ func startHTTPHandler(state *State) {
param.ErrorMessage,
)

if *logToClient {
if viper.GetBool("enable-log-to-client") {
hostname := strings.Split(param.Request.Host, ":")[0]
loc, ok := state.HTTPListeners.Load(hostname)
if ok {
proxyHolder := loc.(*ProxyHolder)
sendMessage(proxyHolder.SSHConn, strings.TrimSpace(logLine), true)
proxyHolder := loc.(*utils.ProxyHolder)
proxyHolder.SSHConn.SendMessage(strings.TrimSpace(logLine), true)
}
}

return logLine
}), gin.Recovery(), func(c *gin.Context) {
hostname := strings.Split(c.Request.Host, ":")[0]
hostIsRoot := hostname == *rootDomain
hostIsRoot := hostname == viper.GetString("domain")

if (*adminEnabled || *serviceConsoleEnabled) && strings.HasPrefix(c.Request.URL.Path, "/_sish/") {
if (viper.GetBool("enable-admin-console") || viper.GetBool("enable-service-console")) && strings.HasPrefix(c.Request.URL.Path, "/_sish/") {
state.Console.HandleRequest(hostname, hostIsRoot, c)
return
}

if hostIsRoot && *redirectRoot {
c.Redirect(http.StatusFound, *redirectRootLocation)
if hostIsRoot && viper.GetBool("enable-redirect-root") {
c.Redirect(http.StatusFound, viper.GetString("redirect-root-location"))
return
}

Expand Down Expand Up @@ -130,7 +125,7 @@ func startHTTPHandler(state *State) {

c.Request.Header.Set("X-Forwarded-Proto", requestedScheme)

proxyHolder := loc.(*ProxyHolder)
proxyHolder := loc.(*utils.ProxyHolder)

url := *c.Request.URL
url.Host = "local"
Expand All @@ -144,7 +139,7 @@ func startHTTPHandler(state *State) {
}

tlsConfig := &tls.Config{
InsecureSkipVerify: !*verifySSL,
InsecureSkipVerify: !viper.GetBool("verify-ssl"),
}

if c.IsWebsocket() {
Expand All @@ -154,7 +149,7 @@ func startHTTPHandler(state *State) {
}

var checkOrigin func(r *http.Request) bool
if !*verifyOrigin {
if !viper.GetBool("verify-origin") {
checkOrigin = func(r *http.Request) bool {
return true
}
Expand All @@ -181,7 +176,7 @@ func startHTTPHandler(state *State) {
TLSClientConfig: tlsConfig,
}

if *adminEnabled || *serviceConsoleEnabled {
if viper.GetBool("enable-admin-console") || viper.GetBool("enable-service-console") {
proxy.ModifyResponse = func(response *http.Response) error {
resBody, err := ioutil.ReadAll(response.Body)
if err != nil {
Expand Down Expand Up @@ -243,10 +238,10 @@ func startHTTPHandler(state *State) {
gin.WrapH(proxy)(c)
})

if *httpsEnabled {
if viper.GetBool("enable-https") {
go func() {
log.Fatal(r.RunTLS(*httpsAddr, filepath.Join(*httpsPems, "fullchain.pem"), filepath.Join(*httpsPems, "privkey.pem")))
log.Fatal(r.RunTLS(viper.GetString("https-address"), filepath.Join(viper.GetString("certificate-directory"), "fullchain.pem"), filepath.Join(viper.GetString("certificate-directory"), "privkey.pem")))
}()
}
log.Fatal(r.Run(*httpAddr))
log.Fatal(r.Run(viper.GetString("http-address")))
}
Empty file removed keys/.gitkeep
Empty file.
Loading

0 comments on commit d5af803

Please sign in to comment.