Skip to content

Commit

Permalink
feat: wildcard support
Browse files Browse the repository at this point in the history
  • Loading branch information
zk-steve authored and antoniomika committed Oct 7, 2023
1 parent 1a1a572 commit 26cc685
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ Flags:
--bind-random-subdomains Force bound HTTP tunnels to use random subdomains instead of user provided ones (default true)
--bind-random-subdomains-length int The length of the random subdomain to generate if a subdomain is unavailable or if random subdomains are enforced (default 3)
--bind-root-domain Allow binding the root domain when accepting an HTTP listener
--bind-wildcards Allow binding wildcards when accepting an HTTP listener
--cleanup-unauthed Cleanup unauthed SSH connections after a set timeout (default true)
--cleanup-unauthed-timeout duration Duration to wait before cleaning up an unauthed connection (default 5s)
--cleanup-unbound Cleanup unbound (unforwarded) SSH connections after a set timeout
Expand Down
1 change: 1 addition & 0 deletions cmd/sish.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func init() {
rootCmd.PersistentFlags().BoolP("strip-http-path", "", true, "Strip the http path from the forward")
rootCmd.PersistentFlags().BoolP("bind-any-host", "", false, "Allow binding any host when accepting an HTTP listener")
rootCmd.PersistentFlags().BoolP("bind-root-domain", "", false, "Allow binding the root domain when accepting an HTTP listener")
rootCmd.PersistentFlags().BoolP("bind-wildcards", "", false, "Allow binding wildcards when accepting an HTTP listener")
rootCmd.PersistentFlags().BoolP("load-templates", "", true, "Load HTML templates. This is required for admin/service consoles")
rootCmd.PersistentFlags().BoolP("rewrite-host-header", "", true, "Force rewrite the host header if the user provides host-header=host.com")

Expand Down
1 change: 1 addition & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ bind-random-ports: true
bind-random-subdomains: true
bind-random-subdomains-length: 3
bind-root-domain: false
bind-wildcards: false
cleanup-unauthed: true
cleanup-unauthed-timeout: 5s
cleanup-unbound: false
Expand Down
17 changes: 16 additions & 1 deletion httpmuxer/httpmuxer.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func Start(state *utils.State) {
requestUsername, requestPassword, _ := c.Request.BasicAuth()
authNeeded := true

// Loop for checking if there's a listener with auth set (most specific)
state.HTTPListeners.Range(func(key string, locationListener *utils.HTTPHolder) bool {
parsedPassword, _ := locationListener.HTTPUrl.User.Password()

Expand All @@ -191,6 +192,7 @@ func Start(state *utils.State) {
return true
})

// Loop for checking if there's a listener with the exact host and path prefix set (next most specific)
if currentListener == nil {
state.HTTPListeners.Range(func(key string, locationListener *utils.HTTPHolder) bool {
if hostname == locationListener.HTTPUrl.Host && strings.HasPrefix(c.Request.URL.Path, locationListener.HTTPUrl.Path) {
Expand All @@ -203,6 +205,19 @@ func Start(state *utils.State) {
})
}

// Loop for checking if there's a wildcard listener with the host and path prefix set (least most specific)
if currentListener == nil {
state.HTTPListeners.Range(func(key string, locationListener *utils.HTTPHolder) bool {
if utils.MatchesWildcardHost(hostname, locationListener.HTTPUrl.Host) && strings.HasPrefix(c.Request.URL.Path, locationListener.HTTPUrl.Path) {
currentListener = locationListener
authNeeded = false
return false
}

return true
})
}

if currentListener == nil && hostIsRoot {
if viper.GetBool("redirect-root") && !strings.HasPrefix(c.Request.URL.Path, "/favicon.ico") {
c.Redirect(http.StatusFound, viper.GetString("redirect-root-location"))
Expand Down Expand Up @@ -339,7 +354,7 @@ func Start(state *utils.State) {
ok := false

state.HTTPListeners.Range(func(key string, locationListener *utils.HTTPHolder) bool {
if name == locationListener.HTTPUrl.Host {
if name == locationListener.HTTPUrl.Host || utils.MatchesWildcardHost(name, locationListener.HTTPUrl.Host) {
ok = true
return false
}
Expand Down
17 changes: 17 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ import (
const (
// sishDNSPrefix is the prefix used for DNS TXT records.
sishDNSPrefix = "sish="

// Prefix used for defining wildcard host matchers.
wildcardPrefix = "*."
)

var (
Expand Down Expand Up @@ -923,6 +926,11 @@ func GetOpenHost(addr string, state *State, sshConn *SSHConnection) (*url.URL, *
host = getRandomHost()
}

if !viper.GetBool("bind-wildcards") && strings.HasPrefix(host, wildcardPrefix) {
reportUnavailable(true)
host = getRandomHost()
}

var holder *HTTPHolder
ok := false

Expand Down Expand Up @@ -1057,3 +1065,12 @@ func RandStringBytesMaskImprSrc(n int) string {

return string(b)
}

// MatchesWildcardHost checks if the hostname provided would match the potential wildcard

Check failure on line 1069 in utils/utils.go

View workflow job for this annotation

GitHub Actions / test

Comment should end in a period (godot)
func MatchesWildcardHost(hostname string, potentialWildcard string) bool {
if !strings.Contains(potentialWildcard, wildcardPrefix) {
return false
}

return strings.HasPrefix(potentialWildcard, wildcardPrefix) && strings.HasSuffix(hostname, strings.TrimPrefix(potentialWildcard, wildcardPrefix))
}

0 comments on commit 26cc685

Please sign in to comment.