mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 23:24:01 +03:00
Add whitelist support
This commit is contained in:
@@ -174,6 +174,27 @@ urls = [
|
|||||||
# How often do we need to update a blocklist set.
|
# How often do we need to update a blocklist set.
|
||||||
update-each = "24h"
|
update-each = "24h"
|
||||||
|
|
||||||
|
# Allowlist is an opposite to a blocklist. Only those IPs that are coming from
|
||||||
|
# subnets defined in these lists are allowed. All others will be rejected.
|
||||||
|
#
|
||||||
|
# If this feature is disabled, then there won't be any check performed by this
|
||||||
|
# validator. It is possible to combine both blocklist and whitelist.
|
||||||
|
[defense.allowlist]
|
||||||
|
# You can enable/disable this feature.
|
||||||
|
enabled = false
|
||||||
|
# This is a limiter for concurrency. In order to protect website
|
||||||
|
# from overloading, we download files in this number of threads.
|
||||||
|
download-concurrency = 2
|
||||||
|
# A list of URLs in FireHOL format (https://iplists.firehol.org/)
|
||||||
|
# You can provider links here (starts with https:// or http://) or
|
||||||
|
# path to a local file, but in this case it should be absolute.
|
||||||
|
urls = [
|
||||||
|
# "https://iplists.firehol.org/files/firehol_level1.netset",
|
||||||
|
# "/local.file"
|
||||||
|
|
||||||
|
]
|
||||||
|
update-each = "24h"
|
||||||
|
|
||||||
# statsd statistics integration.
|
# statsd statistics integration.
|
||||||
[stats.statsd]
|
[stats.statsd]
|
||||||
# enabled/disabled
|
# enabled/disabled
|
||||||
|
|||||||
@@ -86,15 +86,15 @@ func makeAntiReplayCache(conf *config.Config) mtglib.AntiReplayCache {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeIPBlocklist(conf *config.Config, logger mtglib.Logger, ntw mtglib.Network) (mtglib.IPBlocklist, error) {
|
func makeIPBlocklist(conf config.ListConfig, logger mtglib.Logger, ntw mtglib.Network) (mtglib.IPBlocklist, error) {
|
||||||
if !conf.Defense.Blocklist.Enabled.Get(false) {
|
if !conf.Enabled.Get(false) {
|
||||||
return ipblocklist.NewNoop(), nil
|
return ipblocklist.NewNoop(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteURLs := []string{}
|
remoteURLs := []string{}
|
||||||
localFiles := []string{}
|
localFiles := []string{}
|
||||||
|
|
||||||
for _, v := range conf.Defense.Blocklist.URLs {
|
for _, v := range conf.URLs {
|
||||||
if v.IsRemote() {
|
if v.IsRemote() {
|
||||||
remoteURLs = append(remoteURLs, v.String())
|
remoteURLs = append(remoteURLs, v.String())
|
||||||
} else {
|
} else {
|
||||||
@@ -104,7 +104,7 @@ func makeIPBlocklist(conf *config.Config, logger mtglib.Logger, ntw mtglib.Netwo
|
|||||||
|
|
||||||
firehol, err := ipblocklist.NewFirehol(logger.Named("ipblockist"),
|
firehol, err := ipblocklist.NewFirehol(logger.Named("ipblockist"),
|
||||||
ntw,
|
ntw,
|
||||||
conf.Defense.Blocklist.DownloadConcurrency.Get(1),
|
conf.DownloadConcurrency.Get(1),
|
||||||
remoteURLs,
|
remoteURLs,
|
||||||
localFiles)
|
localFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,7 +153,7 @@ func makeEventStream(conf *config.Config, logger mtglib.Logger) (mtglib.EventStr
|
|||||||
return events.NewNoopStream(), nil
|
return events.NewNoopStream(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runProxy(conf *config.Config, version string) error {
|
func runProxy(conf *config.Config, version string) error { // nolint: funlen
|
||||||
logger := makeLogger(conf)
|
logger := makeLogger(conf)
|
||||||
|
|
||||||
logger.BindJSON("configuration", conf.String()).Debug("configuration")
|
logger.BindJSON("configuration", conf.String()).Debug("configuration")
|
||||||
@@ -163,11 +163,22 @@ func runProxy(conf *config.Config, version string) error {
|
|||||||
return fmt.Errorf("cannot build network: %w", err)
|
return fmt.Errorf("cannot build network: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blocklist, err := makeIPBlocklist(conf, logger, ntw)
|
blocklist, err := makeIPBlocklist(conf.Defense.Blocklist, logger, ntw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot build ip blocklist: %w", err)
|
return fmt.Errorf("cannot build ip blocklist: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var whitelist mtglib.IPBlocklist
|
||||||
|
|
||||||
|
if conf.Defense.Allowlist.Enabled.Get(false) {
|
||||||
|
whlist, err := makeIPBlocklist(conf.Defense.Allowlist, logger, ntw)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot build ip blocklist: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
whitelist = whlist
|
||||||
|
}
|
||||||
|
|
||||||
eventStream, err := makeEventStream(conf, logger)
|
eventStream, err := makeEventStream(conf, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot build event stream: %w", err)
|
return fmt.Errorf("cannot build event stream: %w", err)
|
||||||
@@ -178,6 +189,7 @@ func runProxy(conf *config.Config, version string) error {
|
|||||||
Network: ntw,
|
Network: ntw,
|
||||||
AntiReplayCache: makeAntiReplayCache(conf),
|
AntiReplayCache: makeAntiReplayCache(conf),
|
||||||
IPBlocklist: blocklist,
|
IPBlocklist: blocklist,
|
||||||
|
IPWhitelist: whitelist,
|
||||||
EventStream: eventStream,
|
EventStream: eventStream,
|
||||||
|
|
||||||
Secret: conf.Secret,
|
Secret: conf.Secret,
|
||||||
|
|||||||
@@ -8,6 +8,18 @@ import (
|
|||||||
"github.com/9seconds/mtg/v2/mtglib"
|
"github.com/9seconds/mtg/v2/mtglib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Optional struct {
|
||||||
|
Enabled TypeBool `json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListConfig struct {
|
||||||
|
Optional
|
||||||
|
|
||||||
|
DownloadConcurrency TypeConcurrency `json:"downloadConcurrency"`
|
||||||
|
URLs []TypeBlocklistURI `json:"urls"`
|
||||||
|
UpdateEach TypeDuration `json:"updateEach"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Debug TypeBool `json:"debug"`
|
Debug TypeBool `json:"debug"`
|
||||||
AllowFallbackOnUnknownDC TypeBool `json:"allowFallbackOnUnknownDc"`
|
AllowFallbackOnUnknownDC TypeBool `json:"allowFallbackOnUnknownDc"`
|
||||||
@@ -20,16 +32,13 @@ type Config struct {
|
|||||||
Concurrency TypeConcurrency `json:"concurrency"`
|
Concurrency TypeConcurrency `json:"concurrency"`
|
||||||
Defense struct {
|
Defense struct {
|
||||||
AntiReplay struct {
|
AntiReplay struct {
|
||||||
Enabled TypeBool `json:"enabled"`
|
Optional
|
||||||
|
|
||||||
MaxSize TypeBytes `json:"maxSize"`
|
MaxSize TypeBytes `json:"maxSize"`
|
||||||
ErrorRate TypeErrorRate `json:"errorRate"`
|
ErrorRate TypeErrorRate `json:"errorRate"`
|
||||||
} `json:"antiReplay"`
|
} `json:"antiReplay"`
|
||||||
Blocklist struct {
|
Blocklist ListConfig `json:"blocklist"`
|
||||||
Enabled TypeBool `json:"enabled"`
|
Allowlist ListConfig `json:"allowlist"`
|
||||||
DownloadConcurrency TypeConcurrency `json:"downloadConcurrency"`
|
|
||||||
URLs []TypeBlocklistURI `json:"urls"`
|
|
||||||
UpdateEach TypeDuration `json:"updateEach"`
|
|
||||||
} `json:"blocklist"`
|
|
||||||
} `json:"defense"`
|
} `json:"defense"`
|
||||||
Network struct {
|
Network struct {
|
||||||
Timeout struct {
|
Timeout struct {
|
||||||
@@ -42,13 +51,15 @@ type Config struct {
|
|||||||
} `json:"network"`
|
} `json:"network"`
|
||||||
Stats struct {
|
Stats struct {
|
||||||
StatsD struct {
|
StatsD struct {
|
||||||
Enabled TypeBool `json:"enabled"`
|
Optional
|
||||||
|
|
||||||
Address TypeHostPort `json:"address"`
|
Address TypeHostPort `json:"address"`
|
||||||
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
||||||
TagFormat TypeStatsdTagFormat `json:"tagFormat"`
|
TagFormat TypeStatsdTagFormat `json:"tagFormat"`
|
||||||
} `json:"statsd"`
|
} `json:"statsd"`
|
||||||
Prometheus struct {
|
Prometheus struct {
|
||||||
Enabled TypeBool `json:"enabled"`
|
Optional
|
||||||
|
|
||||||
BindTo TypeHostPort `json:"bindTo"`
|
BindTo TypeHostPort `json:"bindTo"`
|
||||||
HTTPPath TypeHTTPPath `json:"httpPath"`
|
HTTPPath TypeHTTPPath `json:"httpPath"`
|
||||||
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ type tomlConfig struct {
|
|||||||
URLs []string `toml:"urls" json:"urls,omitempty"`
|
URLs []string `toml:"urls" json:"urls,omitempty"`
|
||||||
UpdateEach string `toml:"update-each" json:"updateEach,omitempty"`
|
UpdateEach string `toml:"update-each" json:"updateEach,omitempty"`
|
||||||
} `toml:"blocklist" json:"blocklist,omitempty"`
|
} `toml:"blocklist" json:"blocklist,omitempty"`
|
||||||
|
Allowlist struct {
|
||||||
|
Enabled bool `toml:"enabled" json:"enabled,omitempty"`
|
||||||
|
DownloadConcurrency uint `toml:"download-concurrency" json:"downloadConcurrency,omitempty"`
|
||||||
|
URLs []string `toml:"urls" json:"urls,omitempty"`
|
||||||
|
UpdateEach string `toml:"update-each" json:"updateEach,omitempty"`
|
||||||
|
} `toml:"allowlist" json:"allowlist,omitempty"`
|
||||||
} `toml:"defense" json:"defense,omitempty"`
|
} `toml:"defense" json:"defense,omitempty"`
|
||||||
Network struct {
|
Network struct {
|
||||||
Timeout struct {
|
Timeout struct {
|
||||||
|
|||||||
+14
-4
@@ -33,7 +33,8 @@ type Proxy struct {
|
|||||||
secret Secret
|
secret Secret
|
||||||
network Network
|
network Network
|
||||||
antiReplayCache AntiReplayCache
|
antiReplayCache AntiReplayCache
|
||||||
ipBlocklist IPBlocklist
|
blocklist IPBlocklist
|
||||||
|
whitelist IPBlocklist
|
||||||
eventStream EventStream
|
eventStream EventStream
|
||||||
logger Logger
|
logger Logger
|
||||||
}
|
}
|
||||||
@@ -91,7 +92,7 @@ func (p *Proxy) ServeConn(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serve starts a proxy on a given listener.
|
// Serve starts a proxy on a given listener.
|
||||||
func (p *Proxy) Serve(listener net.Listener) error {
|
func (p *Proxy) Serve(listener net.Listener) error { // nolint: cyclop
|
||||||
p.streamWaitGroup.Add(1)
|
p.streamWaitGroup.Add(1)
|
||||||
defer p.streamWaitGroup.Done()
|
defer p.streamWaitGroup.Done()
|
||||||
|
|
||||||
@@ -109,7 +110,15 @@ func (p *Proxy) Serve(listener net.Listener) error {
|
|||||||
ipAddr := conn.RemoteAddr().(*net.TCPAddr).IP
|
ipAddr := conn.RemoteAddr().(*net.TCPAddr).IP
|
||||||
logger := p.logger.BindStr("ip", ipAddr.String())
|
logger := p.logger.BindStr("ip", ipAddr.String())
|
||||||
|
|
||||||
if p.ipBlocklist.Contains(ipAddr) {
|
if p.whitelist != nil && !p.whitelist.Contains(ipAddr) {
|
||||||
|
conn.Close()
|
||||||
|
logger.Info("ip was rejected by whitelist")
|
||||||
|
p.eventStream.Send(p.ctx, NewEventIPBlocklisted(ipAddr))
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.blocklist.Contains(ipAddr) {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
logger.Info("ip was blacklisted")
|
logger.Info("ip was blacklisted")
|
||||||
p.eventStream.Send(p.ctx, NewEventIPBlocklisted(ipAddr))
|
p.eventStream.Send(p.ctx, NewEventIPBlocklisted(ipAddr))
|
||||||
@@ -291,7 +300,8 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) {
|
|||||||
secret: opts.Secret,
|
secret: opts.Secret,
|
||||||
network: opts.Network,
|
network: opts.Network,
|
||||||
antiReplayCache: opts.AntiReplayCache,
|
antiReplayCache: opts.AntiReplayCache,
|
||||||
ipBlocklist: opts.IPBlocklist,
|
blocklist: opts.IPBlocklist,
|
||||||
|
whitelist: opts.IPWhitelist,
|
||||||
eventStream: opts.EventStream,
|
eventStream: opts.EventStream,
|
||||||
logger: opts.getLogger("proxy"),
|
logger: opts.getLogger("proxy"),
|
||||||
domainFrontingPort: opts.getDomainFrontingPort(),
|
domainFrontingPort: opts.getDomainFrontingPort(),
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ type ProxyOpts struct {
|
|||||||
// This is a mandatory setting.
|
// This is a mandatory setting.
|
||||||
IPBlocklist IPBlocklist
|
IPBlocklist IPBlocklist
|
||||||
|
|
||||||
|
// IPWhitelist defines a whitelist of IPs to allow to use proxy.
|
||||||
|
//
|
||||||
|
// This is an optional setting, ignored by default (no restrictions).
|
||||||
|
IPWhitelist IPBlocklist
|
||||||
|
|
||||||
// EventStream defines an instance of event stream.
|
// EventStream defines an instance of event stream.
|
||||||
//
|
//
|
||||||
// This ia a mandatory setting.
|
// This ia a mandatory setting.
|
||||||
|
|||||||
Reference in New Issue
Block a user