mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-10 10:38:45 +00:00
Compare commits
4 Commits
vic/set-co
...
Xe/checker
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
208ceca723 | ||
|
|
dc0dde3053 | ||
|
|
292c470ada | ||
|
|
12453fdc00 |
@@ -51,6 +51,7 @@ var (
|
||||
cookiePrefix = flag.String("cookie-prefix", "techaro.lol-anubis", "prefix for browser cookies created by Anubis")
|
||||
cookiePartitioned = flag.Bool("cookie-partitioned", false, "if true, sets the partitioned flag on Anubis cookies, enabling CHIPS support")
|
||||
hs512Secret = flag.String("hs512-secret", "", "secret used to sign JWTs, uses ed25519 if not set")
|
||||
cookieSecure = flag.Bool("cookie-secure", true, "if true, sets the secure flag on Anubis cookies")
|
||||
ed25519PrivateKeyHex = flag.String("ed25519-private-key-hex", "", "private key used to sign JWTs, if not set a random one will be assigned")
|
||||
ed25519PrivateKeyHexFile = flag.String("ed25519-private-key-hex-file", "", "file name containing value for ed25519-private-key-hex")
|
||||
metricsBind = flag.String("metrics-bind", ":9090", "network address to bind metrics to")
|
||||
@@ -403,6 +404,7 @@ func main() {
|
||||
Target: *target,
|
||||
WebmasterEmail: *webmasterEmail,
|
||||
OpenGraph: policy.OpenGraph,
|
||||
CookieSecure: *cookieSecure,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("can't construct libanubis.Server: %v", err)
|
||||
|
||||
@@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
<!-- This changes the project to: -->
|
||||
- Add `COOKIE_SECURE` option to set the cookie [Secure flag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies#block_access_to_your_cookies)
|
||||
- Sets cookie defaults to use [SameSite: None](https://web.dev/articles/samesite-cookies-explained)
|
||||
|
||||
- Determine the `BIND_NETWORK`/`--bind-network` value from the bind address ([#677](https://github.com/TecharoHQ/anubis/issues/677)).
|
||||
- Implement localization system. Find locale files in lib/localization/locales/.
|
||||
|
||||
@@ -67,6 +67,7 @@ Anubis uses these environment variables for configuration:
|
||||
| `COOKIE_DYNAMIC_DOMAIN` | false | If set to true, automatically set cookie domain fields based on the hostname of the request. EG: if you are making a request to `anubis.techaro.lol`, the Anubis cookie will be valid for any subdomain of `techaro.lol`. |
|
||||
| `COOKIE_EXPIRATION_TIME` | `168h` | The amount of time the authorization cookie is valid for. |
|
||||
| `COOKIE_PARTITIONED` | `false` | If set to `true`, enables the [partitioned (CHIPS) flag](https://developers.google.com/privacy-sandbox/cookies/chips), meaning that Anubis inside an iframe has a different set of cookies than the domain hosting the iframe. |
|
||||
| `COOKIE_SECURE` | `true` | If set to `true`, enables the [Secure flag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies#block_access_to_your_cookies), meaning that the cookies will only be transmitted over HTTPS. If Anubis is used in an unsecure context (plain HTTP), this will be need to be set to false |
|
||||
| `DIFFICULTY` | `4` | The difficulty of the challenge, or the number of leading zeroes that must be in successful responses. |
|
||||
| `ED25519_PRIVATE_KEY_HEX` | unset | The hex-encoded ed25519 private key used to sign Anubis responses. If this is not set, Anubis will generate one for you. This should be exactly 64 characters long. See below for details. |
|
||||
| `ED25519_PRIVATE_KEY_HEX_FILE` | unset | Path to a file containing the hex-encoded ed25519 private key. Only one of this or its sister option may be set. |
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
iptoasnv1 "github.com/TecharoHQ/thoth-proto/gen/techaro/thoth/iptoasn/v1"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal/thoth"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
iptoasnv1 "github.com/TecharoHQ/thoth-proto/gen/techaro/thoth/iptoasn/v1"
|
||||
)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
iptoasnv1 "github.com/TecharoHQ/thoth-proto/gen/techaro/thoth/iptoasn/v1"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal/thoth"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
)
|
||||
|
||||
var _ checker.Impl = &thoth.GeoIPChecker{}
|
||||
|
||||
@@ -26,14 +26,17 @@ import (
|
||||
"github.com/TecharoHQ/anubis/internal/dnsbl"
|
||||
"github.com/TecharoHQ/anubis/internal/ogtags"
|
||||
"github.com/TecharoHQ/anubis/lib/challenge"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/localization"
|
||||
"github.com/TecharoHQ/anubis/lib/policy"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
|
||||
// challenge implementations
|
||||
_ "github.com/TecharoHQ/anubis/lib/challenge/metarefresh"
|
||||
_ "github.com/TecharoHQ/anubis/lib/challenge/proofofwork"
|
||||
|
||||
// checker implementations
|
||||
_ "github.com/TecharoHQ/anubis/lib/checker/remoteaddress"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -262,6 +262,7 @@ func TestCookieSettings(t *testing.T) {
|
||||
|
||||
CookieDomain: "127.0.0.1",
|
||||
CookiePartitioned: true,
|
||||
CookieSecure: true,
|
||||
CookieExpiration: anubis.CookieDefaultExpirationTime,
|
||||
})
|
||||
|
||||
@@ -309,6 +310,10 @@ func TestCookieSettings(t *testing.T) {
|
||||
if ckie.Partitioned != srv.opts.CookiePartitioned {
|
||||
t.Errorf("wanted partitioned flag %v, got: %v", srv.opts.CookiePartitioned, ckie.Partitioned)
|
||||
}
|
||||
|
||||
if ckie.Secure != srv.opts.CookieSecure {
|
||||
t.Errorf("wanted secure flag %v, got: %v", srv.opts.CookieSecure, ckie.Secure)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckDefaultDifficultyMatchesPolicy(t *testing.T) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type Impl interface {
|
||||
Check(*http.Request) (bool, error)
|
||||
Check(*http.Request) (matches bool, err error)
|
||||
Hash() string
|
||||
}
|
||||
|
||||
42
lib/checker/registry.go
Normal file
42
lib/checker/registry.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package checker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Factory interface {
|
||||
ValidateConfig(json.RawMessage) error
|
||||
Create(json.RawMessage) (Impl, error)
|
||||
}
|
||||
|
||||
var (
|
||||
registry map[string]Factory = map[string]Factory{}
|
||||
regLock sync.RWMutex
|
||||
)
|
||||
|
||||
func Register(name string, factory Factory) {
|
||||
regLock.Lock()
|
||||
defer regLock.Unlock()
|
||||
|
||||
registry[name] = factory
|
||||
}
|
||||
|
||||
func Get(name string) (Factory, bool) {
|
||||
regLock.RLock()
|
||||
defer regLock.RUnlock()
|
||||
result, ok := registry[name]
|
||||
return result, ok
|
||||
}
|
||||
|
||||
func Methods() []string {
|
||||
regLock.RLock()
|
||||
defer regLock.RUnlock()
|
||||
var result []string
|
||||
for method := range registry {
|
||||
result = append(result, method)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
106
lib/checker/remoteaddress/remoteaddress.go
Normal file
106
lib/checker/remoteaddress/remoteaddress.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package remoteaddress
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/policy"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
"github.com/gaissmai/bart"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoRemoteAddresses = errors.New("remoteaddress: no remote addresses defined")
|
||||
)
|
||||
|
||||
func init() {
|
||||
checker.Register("remote_address", Factory{})
|
||||
}
|
||||
|
||||
type Factory struct{}
|
||||
|
||||
func (Factory) ValidateConfig(inp json.RawMessage) error {
|
||||
var fc fileConfig
|
||||
if err := json.Unmarshal([]byte(inp), &fc); err != nil {
|
||||
return fmt.Errorf("%w: %w", config.ErrUnparseableConfig, err)
|
||||
}
|
||||
|
||||
if err := fc.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (Factory) Create(inp json.RawMessage) (checker.Impl, error) {
|
||||
c := struct {
|
||||
RemoteAddr []netip.Prefix `json:"remote_addresses,omitempty" yaml:"remote_addresses,omitempty"`
|
||||
}{}
|
||||
|
||||
if err := json.Unmarshal([]byte(inp), &c); err != nil {
|
||||
return nil, fmt.Errorf("%w: %w", config.ErrUnparseableConfig, err)
|
||||
}
|
||||
|
||||
table := new(bart.Lite)
|
||||
|
||||
for _, cidr := range c.RemoteAddr {
|
||||
table.Insert(cidr)
|
||||
}
|
||||
|
||||
return &Impl{
|
||||
prefixTable: table,
|
||||
hash: internal.FastHash(string(inp)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type fileConfig struct {
|
||||
RemoteAddr []string `json:"remote_addresses,omitempty" yaml:"remote_addresses,omitempty"`
|
||||
}
|
||||
|
||||
func (fc fileConfig) Valid() error {
|
||||
var errs []error
|
||||
|
||||
if len(fc.RemoteAddr) == 0 {
|
||||
errs = append(errs, ErrNoRemoteAddresses)
|
||||
}
|
||||
|
||||
for _, cidr := range fc.RemoteAddr {
|
||||
if _, err := netip.ParsePrefix(cidr); err != nil {
|
||||
errs = append(errs, fmt.Errorf("%w: cidr %q is invalid: %w", config.ErrInvalidCIDR, cidr, err))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) != 0 {
|
||||
return fmt.Errorf("%w: %w", policy.ErrMisconfiguration, errors.Join(errs...))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Impl struct {
|
||||
prefixTable *bart.Lite
|
||||
hash string
|
||||
}
|
||||
|
||||
func (rac *Impl) Check(r *http.Request) (bool, error) {
|
||||
host := r.Header.Get("X-Real-Ip")
|
||||
if host == "" {
|
||||
return false, fmt.Errorf("%w: header X-Real-Ip is not set", policy.ErrMisconfiguration)
|
||||
}
|
||||
|
||||
addr, err := netip.ParseAddr(host)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("%w: %s is not an IP address: %w", policy.ErrMisconfiguration, host, err)
|
||||
}
|
||||
|
||||
return rac.prefixTable.Contains(addr), nil
|
||||
}
|
||||
|
||||
func (rac *Impl) Hash() string {
|
||||
return rac.hash
|
||||
}
|
||||
238
lib/checker/remoteaddress/remoteaddress_test.go
Normal file
238
lib/checker/remoteaddress/remoteaddress_test.go
Normal file
@@ -0,0 +1,238 @@
|
||||
package remoteaddress
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/policy"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
"github.com/gaissmai/bart"
|
||||
)
|
||||
|
||||
func TestFactoryIsCheckerFactory(t *testing.T) {
|
||||
if _, ok := (any(Factory{})).(checker.Factory); !ok {
|
||||
t.Fatal("Factory is not an instance of checker.Factory")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFactoryValidateConfig(t *testing.T) {
|
||||
f := Factory{}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
data []byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "basic valid",
|
||||
data: []byte(`{
|
||||
"remote_addresses": [
|
||||
"1.1.1.1/32"
|
||||
]
|
||||
}`),
|
||||
},
|
||||
{
|
||||
name: "not json",
|
||||
data: []byte(`]`),
|
||||
err: config.ErrUnparseableConfig,
|
||||
},
|
||||
{
|
||||
name: "no cidr",
|
||||
data: []byte(`{
|
||||
"remote_addresses": []
|
||||
}`),
|
||||
err: ErrNoRemoteAddresses,
|
||||
},
|
||||
{
|
||||
name: "bad cidr",
|
||||
data: []byte(`{
|
||||
"remote_addresses": [
|
||||
"according to all laws of aviation"
|
||||
]
|
||||
}`),
|
||||
err: config.ErrInvalidCIDR,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
data := json.RawMessage(tt.data)
|
||||
|
||||
if err := f.ValidateConfig(data); !errors.Is(err, tt.err) {
|
||||
t.Logf("want: %v", tt.err)
|
||||
t.Logf("got: %v", err)
|
||||
t.Fatal("validation didn't do what was expected")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFactoryCreate(t *testing.T) {
|
||||
f := Factory{}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
data []byte
|
||||
err error
|
||||
ip string
|
||||
match bool
|
||||
}{
|
||||
{
|
||||
name: "basic valid",
|
||||
data: []byte(`{
|
||||
"remote_addresses": [
|
||||
"1.1.1.1/32"
|
||||
]
|
||||
}`),
|
||||
ip: "1.1.1.1",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
name: "bad cidr",
|
||||
data: []byte(`{
|
||||
"remote_addresses": [
|
||||
"according to all laws of aviation"
|
||||
]
|
||||
}`),
|
||||
err: config.ErrUnparseableConfig,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
data := json.RawMessage(tt.data)
|
||||
|
||||
impl, err := f.Create(data)
|
||||
if !errors.Is(err, tt.err) {
|
||||
t.Logf("want: %v", tt.err)
|
||||
t.Logf("got: %v", err)
|
||||
t.Fatal("creation didn't do what was expected")
|
||||
}
|
||||
|
||||
if tt.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make request: %v", err)
|
||||
}
|
||||
|
||||
if tt.ip != "" {
|
||||
r.Header.Add("X-Real-Ip", tt.ip)
|
||||
}
|
||||
|
||||
match, err := impl.Check(r)
|
||||
|
||||
if tt.match != match {
|
||||
t.Errorf("match: %v, wanted: %v", match, tt.match)
|
||||
}
|
||||
|
||||
if err != nil && tt.err != nil && !errors.Is(err, tt.err) {
|
||||
t.Errorf("err: %v, wanted: %v", err, tt.err)
|
||||
}
|
||||
|
||||
if impl.Hash() == "" {
|
||||
t.Error("hash method returns empty string")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func racFromCidrs(t *testing.T, inp []string) *Impl {
|
||||
t.Helper()
|
||||
|
||||
var result Impl
|
||||
result.prefixTable = new(bart.Lite)
|
||||
result.hash = internal.FastHash(strings.Join(inp, ","))
|
||||
|
||||
for _, cidr := range inp {
|
||||
pfx, err := netip.ParsePrefix(cidr)
|
||||
if err != nil {
|
||||
t.Errorf("prefix %q is invalid: %v", cidr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
result.prefixTable.Insert(pfx)
|
||||
}
|
||||
|
||||
return &result
|
||||
}
|
||||
|
||||
func TestRemoteAddrChecker(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
err error
|
||||
name string
|
||||
ip string
|
||||
cidrs []string
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
name: "match_ipv4",
|
||||
cidrs: []string{"0.0.0.0/0"},
|
||||
ip: "1.1.1.1",
|
||||
ok: true,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "match_ipv6",
|
||||
cidrs: []string{"::/0"},
|
||||
ip: "cafe:babe::",
|
||||
ok: true,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "not_match_ipv4",
|
||||
cidrs: []string{"1.1.1.1/32"},
|
||||
ip: "1.1.1.2",
|
||||
ok: false,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "not_match_ipv6",
|
||||
cidrs: []string{"cafe:babe::/128"},
|
||||
ip: "cafe:babe:4::/128",
|
||||
ok: false,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "no_ip_set",
|
||||
cidrs: []string{"::/0"},
|
||||
ok: false,
|
||||
err: policy.ErrMisconfiguration,
|
||||
},
|
||||
{
|
||||
name: "invalid_ip",
|
||||
cidrs: []string{"::/0"},
|
||||
ip: "According to all natural laws of aviation",
|
||||
ok: false,
|
||||
err: policy.ErrMisconfiguration,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rac := racFromCidrs(t, tt.cidrs)
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "/", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make request: %v", err)
|
||||
}
|
||||
|
||||
if tt.ip != "" {
|
||||
r.Header.Add("X-Real-Ip", tt.ip)
|
||||
}
|
||||
|
||||
ok, err := rac.Check(r)
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("ok: %v, wanted: %v", ok, tt.ok)
|
||||
}
|
||||
|
||||
if err != nil && tt.err != nil && !errors.Is(err, tt.err) {
|
||||
t.Errorf("err: %v, wanted: %v", err, tt.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ type Options struct {
|
||||
StripBasePrefix bool
|
||||
OpenGraph config.OpenGraph
|
||||
ServeRobotsTXT bool
|
||||
CookieSecure bool
|
||||
}
|
||||
|
||||
func LoadPoliciesOrDefault(ctx context.Context, fname string, defaultDifficulty int) (*policy.ParsedConfig, error) {
|
||||
|
||||
32
lib/http.go
32
lib/http.go
@@ -23,10 +23,11 @@ import (
|
||||
var domainMatchRegexp = regexp.MustCompile(`^((xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$`)
|
||||
|
||||
type CookieOpts struct {
|
||||
Value string
|
||||
Host string
|
||||
Path string
|
||||
Name string
|
||||
Value string
|
||||
Host string
|
||||
Path string
|
||||
Name string
|
||||
Expiry time.Duration
|
||||
}
|
||||
|
||||
func (s *Server) SetCookie(w http.ResponseWriter, cookieOpts CookieOpts) {
|
||||
@@ -45,12 +46,17 @@ func (s *Server) SetCookie(w http.ResponseWriter, cookieOpts CookieOpts) {
|
||||
}
|
||||
}
|
||||
|
||||
if cookieOpts.Expiry == 0 {
|
||||
cookieOpts.Expiry = s.opts.CookieExpiration
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: name,
|
||||
Value: cookieOpts.Value,
|
||||
Expires: time.Now().Add(s.opts.CookieExpiration),
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Expires: time.Now().Add(cookieOpts.Expiry),
|
||||
SameSite: http.SameSiteNoneMode,
|
||||
Domain: domain,
|
||||
Secure: s.opts.CookieSecure,
|
||||
Partitioned: s.opts.CookiePartitioned,
|
||||
Path: path,
|
||||
})
|
||||
@@ -77,9 +83,10 @@ func (s *Server) ClearCookie(w http.ResponseWriter, cookieOpts CookieOpts) {
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Expires: time.Now().Add(-1 * time.Minute),
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
SameSite: http.SameSiteNoneMode,
|
||||
Partitioned: s.opts.CookiePartitioned,
|
||||
Domain: domain,
|
||||
Secure: s.opts.CookieSecure,
|
||||
Path: path,
|
||||
})
|
||||
}
|
||||
@@ -132,11 +139,12 @@ func (s *Server) RenderIndex(w http.ResponseWriter, r *http.Request, rule *polic
|
||||
}
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: anubis.TestCookieName,
|
||||
Value: challengeStr,
|
||||
Expires: time.Now().Add(30 * time.Minute),
|
||||
Path: "/",
|
||||
s.SetCookie(w, CookieOpts{
|
||||
Value: challengeStr,
|
||||
Host: r.Host,
|
||||
Path: "/",
|
||||
Name: anubis.TestCookieName,
|
||||
Expiry: 30 * time.Minute,
|
||||
})
|
||||
|
||||
impl, ok := challenge.Get(rule.Challenge.Algorithm)
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
"static_check_endpoint": "Este é apenas um ponto de verificação para seu proxy reverso usar.",
|
||||
"authorization_required": "Autorização necessária",
|
||||
"cookies_disabled": "Seu navegador está configurado para desabilitar cookies. O Anubis requer cookies para o interesse legítimo de garantir que você seja um cliente válido. Habilite os cookies para este domínio.",
|
||||
"access_denied": "Acesso negado: código de errado",
|
||||
"access_denied": "Acesso negado: código de erro",
|
||||
"dronebl_entry": "DroneBL relatou uma entrada",
|
||||
"see_dronebl_lookup": "consulte",
|
||||
"internal_server_error": "Erro interno do servidor: o administrador configurou incorretamente o Anubis. Entre em contato com o administrador e peça para ele procurar os logs em torno dele.",
|
||||
"internal_server_error": "Erro interno do servidor: o administrador configurou incorretamente o Anubis. Entre em contato com o administrador e peça para analisar os logs relacionados.",
|
||||
"invalid_redirect": "Redirecionamento inválido",
|
||||
"redirect_not_parseable": "URL de redirecionamento não analisável",
|
||||
"redirect_domain_not_allowed": "Domínio de redirecionamento não permitido",
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/gaissmai/bart"
|
||||
)
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ var (
|
||||
ErrCantSetBotAndImportValuesAtOnce = errors.New("config.BotOrImport: can't set bot rules and import values at the same time")
|
||||
ErrMustSetBotOrImportRules = errors.New("config.BotOrImport: rule definition is invalid, you must set either bot rules or an import statement, not both")
|
||||
ErrStatusCodeNotValid = errors.New("config.StatusCode: status code not valid, must be between 100 and 599")
|
||||
ErrUnparseableConfig = errors.New("config: can't parse configuration file")
|
||||
)
|
||||
|
||||
type Rule string
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal/thoth"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/checker"
|
||||
"github.com/TecharoHQ/anubis/lib/policy/config"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
|
||||
Reference in New Issue
Block a user