Merge branch 'main' into terms_ack

This commit is contained in:
Michael Quigley 2024-07-31 13:39:27 -04:00
commit 4424a909b9
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
5 changed files with 67 additions and 22 deletions

View File

@ -1,5 +1,11 @@
# CHANGELOG # CHANGELOG
## v0.4.38
FEATURE: Conditionally enable interstitial page based on `User-Agent` prefix list. See the [frontend configuration template](etc/frontend.yml) for details on the new configuration structure (https://github.com/openziti/zrok/issues/715)
CHANGE: The interstitial configuration has been modified from a simple `interstitial: <bool>` to a richer structure, but the config version has not been incremented; this feature has not been widely adopted yet. See the [frontend configuration template](etc/frontend.yml) for details on the new structure.
## v0.4.37 ## v0.4.37
FIX: Fix for setting the `zrok_interstitial` cookie on Chrome-based browsers. FIX: Fix for setting the `zrok_interstitial` cookie on Chrome-based browsers.

View File

@ -37,18 +37,28 @@ If an account has a row present in this table when creating a share, then the co
The frontend configuration controls what the frontend will do with the share config it finds in OpenZiti. The new stanza looks like this: The frontend configuration controls what the frontend will do with the share config it finds in OpenZiti. The new stanza looks like this:
``` ```
# Setting the `interstitial` setting to `true` will allow this frontend # Configure interstitial pages for this frontend. The interstitial page presents a warning to internet users, alerting
# to offer interstitial pages if they are configured on the share by the # them to the fact that they're visiting a zrok share.
# controller.
# #
#interstitial: true #interstitial:
# # Enable or disable interstitial pages on this frontend.
# #
# enabled: true
#
# # Specify a list of User-Agent prefixes that should receive the interstitial page. If interstitial pages are enabled
# # and this list is not set, all user agents will receive an interstitial page.
# #
# user_agent_prefixes:
# - "Mozilla/5.0"
``` ```
Simply setting `interstitial: true` in the frontend config will allow the configured frontend to offer an interstitial page if the share config enables the interstitial page for that share. Setting `enabled: true` in the `interstitial` stanza of the frontend config will allow the configured frontend to offer an interstitial page if the share config enables the interstitial page for that share. The `user_agent_prefixes` array can be used to specify which specific `User-Agent` types receive the interstitial. User agents that match a prefix in the list will receive the interstitial, while others will not. If the `user_agent_prefixes` list is omitted, _all_ user agents will receive the interstitial page.
## Bypassing the Interstitial ## Bypassing the Interstitial
The interstitial page will be presented unless the client shows up with a `zrok_interstitial` cookie. When the user is presented with the interstitial page, there is a button they can click which sets the necessary cookie and allows them to visit the site. The cookie is set to expire in one week. The interstitial page will be presented unless the client shows up with a `zrok_interstitial` cookie (depending on `user_agent_prefixes` configuration). When the user is presented with the interstitial page, there is a button they can click which sets the necessary cookie and allows them to visit the site. The cookie is set to expire in one week.
Typically the `user_agent_prefixes` list contains `Mozilla/5.0`, which matches all typical interactive mobile and desktop browsers. Setting a non-standard `User-Agent` in an interactive browser will bypass the interstitial pages for frontends configured with the usual `Mozilla/5.0` prefix.
End users can offer an HTTP header of `skip_zrok_interstitial`, set to any value to bypass the interstitial page. Setting this header means that the user most likely understands what a zrok share is and will hopefully not fall for a phishing attack. End users can offer an HTTP header of `skip_zrok_interstitial`, set to any value to bypass the interstitial page. Setting this header means that the user most likely understands what a zrok share is and will hopefully not fall for a phishing attack.

View File

@ -16,11 +16,16 @@ type Config struct {
Identity string Identity string
Address string Address string
HostMatch string HostMatch string
Interstitial bool Interstitial *InterstitialConfig
Oauth *OauthConfig Oauth *OauthConfig
Tls *endpoints.TlsConfig Tls *endpoints.TlsConfig
} }
type InterstitialConfig struct {
Enabled bool
UserAgentPrefixes []string
}
type OauthConfig struct { type OauthConfig struct {
BindAddress string BindAddress string
RedirectUrl string RedirectUrl string
@ -46,9 +51,8 @@ type OauthProviderConfig struct {
func DefaultConfig() *Config { func DefaultConfig() *Config {
return &Config{ return &Config{
Identity: "public", Identity: "public",
Address: "0.0.0.0:8080", Address: "0.0.0.0:8080",
Interstitial: false,
} }
} }

View File

@ -158,15 +158,31 @@ func shareHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Conte
if shrToken != "" { if shrToken != "" {
if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found { if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found {
if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found { if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found {
if pcfg.Interstitial { if pcfg.Interstitial != nil && pcfg.Interstitial.Enabled {
if v, istlFound := cfg["interstitial"]; istlFound { sendInterstitial := true
if istlEnabled, ok := v.(bool); ok && istlEnabled { if len(pcfg.Interstitial.UserAgentPrefixes) > 0 {
skip := r.Header.Get("skip_zrok_interstitial") ua := r.Header.Get("User-Agent")
_, zrokOkErr := r.Cookie("zrok_interstitial") matched := false
if skip == "" && zrokOkErr != nil { for _, prefix := range pcfg.Interstitial.UserAgentPrefixes {
logrus.Debugf("forcing interstitial for '%v'", r.URL) if strings.HasPrefix(ua, prefix) {
interstitialUi.WriteInterstitialAnnounce(w) matched = true
return break
}
}
if !matched {
sendInterstitial = false
}
}
if sendInterstitial {
if v, istlFound := cfg["interstitial"]; istlFound {
if istlEnabled, ok := v.(bool); ok && istlEnabled {
skip := r.Header.Get("skip_zrok_interstitial")
_, zrokOkErr := r.Cookie("zrok_interstitial")
if skip == "" && zrokOkErr != nil {
logrus.Debugf("forcing interstitial for '%v'", r.URL)
interstitialUi.WriteInterstitialAnnounce(w)
return
}
} }
} }
} }

View File

@ -10,10 +10,19 @@ v: 3
# #
#host_match: zrok.io #host_match: zrok.io
# Setting the `interstitial` setting to `true` will allow this frontend to offer interstitial pages if they are # Configure interstitial pages for this frontend. The interstitial page presents a warning to internet users, alerting
# configured on the share by the controller. # them to the fact that they're visiting a zrok share.
# #
#interstitial: true #interstitial:
# # Enable or disable interstitial pages on this frontend.
# #
# enabled: true
#
# # Specify a list of User-Agent prefixes that should receive the interstitial page. If interstitial pages are enabled
# # and this list is not set, all user agents will receive an interstitial page.
# #
# user_agent_prefixes:
# - "Mozilla/5.0"
# The OAuth configuration is used when enabling OAuth authentication with your public frontend. # The OAuth configuration is used when enabling OAuth authentication with your public frontend.
# #