frontend: update to use non-object sanization
This commit is contained in:
parent
66e12c6684
commit
ca823e0e5f
6 changed files with 65 additions and 80 deletions
|
@ -1,61 +0,0 @@
|
|||
package bittorrent
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ErrInvalidIP indicates an invalid IP for an Announce.
|
||||
var ErrInvalidIP = ClientError("invalid IP")
|
||||
|
||||
// RequestSanitizer is used to replace unreasonable values in requests parsed
|
||||
// from a frontend into sane values.
|
||||
type RequestSanitizer struct {
|
||||
MaxNumWant uint32 `yaml:"max_numwant"`
|
||||
DefaultNumWant uint32 `yaml:"default_numwant"`
|
||||
MaxScrapeInfoHashes uint32 `yaml:"max_scrape_infohashes"`
|
||||
}
|
||||
|
||||
// SanitizeAnnounce enforces a max and default NumWant and coerces the peer's
|
||||
// IP address into the proper format.
|
||||
func (rs *RequestSanitizer) SanitizeAnnounce(r *AnnounceRequest) error {
|
||||
if !r.NumWantProvided {
|
||||
r.NumWant = rs.DefaultNumWant
|
||||
} else if r.NumWant > rs.MaxNumWant {
|
||||
r.NumWant = rs.MaxNumWant
|
||||
}
|
||||
|
||||
if ip := r.Peer.IP.To4(); ip != nil {
|
||||
r.Peer.IP.IP = ip
|
||||
r.Peer.IP.AddressFamily = IPv4
|
||||
} else if len(r.Peer.IP.IP) == net.IPv6len { // implies r.Peer.IP.To4() == nil
|
||||
r.Peer.IP.AddressFamily = IPv6
|
||||
} else {
|
||||
return ErrInvalidIP
|
||||
}
|
||||
|
||||
log.Debug("sanitized announce", rs, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SanitizeScrape enforces a max number of infohashes for a single scrape
|
||||
// request.
|
||||
func (rs *RequestSanitizer) SanitizeScrape(r *ScrapeRequest) error {
|
||||
if len(r.InfoHashes) > int(rs.MaxScrapeInfoHashes) {
|
||||
r.InfoHashes = r.InfoHashes[:rs.MaxScrapeInfoHashes]
|
||||
}
|
||||
|
||||
log.Debug("sanitized scrape", rs, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogFields renders the request sanitizer's configuration as a set of loggable
|
||||
// fields.
|
||||
func (rs *RequestSanitizer) LogFields() log.Fields {
|
||||
return log.Fields{
|
||||
"maxNumWant": rs.MaxNumWant,
|
||||
"defaultNumWant": rs.DefaultNumWant,
|
||||
"maxScrapeInfohashes": rs.MaxScrapeInfoHashes,
|
||||
}
|
||||
}
|
48
bittorrent/sanitize.go
Normal file
48
bittorrent/sanitize.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package bittorrent
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/chihaya/chihaya/pkg/log"
|
||||
)
|
||||
|
||||
// ErrInvalidIP indicates an invalid IP for an Announce.
|
||||
var ErrInvalidIP = ClientError("invalid IP")
|
||||
|
||||
// SanitizeAnnounce enforces a max and default NumWant and coerces the peer's
|
||||
// IP address into the proper format.
|
||||
func SanitizeAnnounce(r *AnnounceRequest, maxNumWant, defaultNumWant uint32) error {
|
||||
if !r.NumWantProvided {
|
||||
r.NumWant = defaultNumWant
|
||||
} else if r.NumWant > maxNumWant {
|
||||
r.NumWant = maxNumWant
|
||||
}
|
||||
|
||||
if ip := r.Peer.IP.To4(); ip != nil {
|
||||
r.Peer.IP.IP = ip
|
||||
r.Peer.IP.AddressFamily = IPv4
|
||||
} else if len(r.Peer.IP.IP) == net.IPv6len { // implies r.Peer.IP.To4() == nil
|
||||
r.Peer.IP.AddressFamily = IPv6
|
||||
} else {
|
||||
return ErrInvalidIP
|
||||
}
|
||||
|
||||
log.Debug("sanitized announce", r, log.Fields{
|
||||
"maxNumWant": maxNumWant,
|
||||
"defaultNumWant": defaultNumWant,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SanitizeScrape enforces a max number of infohashes for a single scrape
|
||||
// request.
|
||||
func SanitizeScrape(r *ScrapeRequest, maxScrapeInfoHashes uint32) error {
|
||||
if len(r.InfoHashes) > int(maxScrapeInfoHashes) {
|
||||
r.InfoHashes = r.InfoHashes[:maxScrapeInfoHashes]
|
||||
}
|
||||
|
||||
log.Debug("sanitized scrape", r, log.Fields{
|
||||
"maxScrapeInfoHashes": maxScrapeInfoHashes,
|
||||
})
|
||||
return nil
|
||||
}
|
|
@ -21,9 +21,6 @@ func init() {
|
|||
prometheus.MustRegister(promResponseDurationMilliseconds)
|
||||
}
|
||||
|
||||
// ErrInvalidIP indicates an invalid IP.
|
||||
var ErrInvalidIP = bittorrent.ClientError("invalid IP")
|
||||
|
||||
var promResponseDurationMilliseconds = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "chihaya_http_response_duration_milliseconds",
|
||||
|
@ -84,7 +81,7 @@ func (cfg Config) LogFields() log.Fields {
|
|||
"realIPHeader": cfg.RealIPHeader,
|
||||
"maxNumWant": cfg.MaxNumWant,
|
||||
"defaultNumWant": cfg.DefaultNumWant,
|
||||
"maxScrapeInfohashes": cfg.MaxScrapeInfoHashes,
|
||||
"maxScrapeInfoHashes": cfg.MaxScrapeInfoHashes,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,7 +277,7 @@ func (f *Frontend) scrapeRoute(w http.ResponseWriter, r *http.Request, _ httprou
|
|||
req.AddressFamily = bittorrent.IPv6
|
||||
} else {
|
||||
log.Error("http: invalid IP: neither v4 nor v6", log.Fields{"RemoteAddr": r.RemoteAddr})
|
||||
WriteError(w, ErrInvalidIP)
|
||||
WriteError(w, bittorrent.ErrInvalidIP)
|
||||
return
|
||||
}
|
||||
af = new(bittorrent.AddressFamily)
|
||||
|
|
|
@ -13,9 +13,11 @@ import (
|
|||
// If RealIPHeader is not empty string, the value of the first HTTP Header with
|
||||
// that name will be used.
|
||||
type ParseOptions struct {
|
||||
AllowIPSpoofing bool `yaml:"allowIPSpoofing"`
|
||||
RealIPHeader string `yaml:"realIPHeader"`
|
||||
bittorrent.RequestSanitizer `yaml:",inline"`
|
||||
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
||||
RealIPHeader string `yaml:"real_ip_header"`
|
||||
MaxNumWant uint32 `yaml:"max_numwant"`
|
||||
DefaultNumWant uint32 `yaml:"default_numwant"`
|
||||
MaxScrapeInfoHashes uint32 `yaml:"max_scrape_infohashes"`
|
||||
}
|
||||
|
||||
// ParseAnnounce parses an bittorrent.AnnounceRequest from an http.Request.
|
||||
|
@ -102,7 +104,7 @@ func ParseAnnounce(r *http.Request, opts ParseOptions) (*bittorrent.AnnounceRequ
|
|||
return nil, bittorrent.ClientError("failed to parse peer IP address")
|
||||
}
|
||||
|
||||
if err := opts.SanitizeAnnounce(request); err != nil {
|
||||
if err := bittorrent.SanitizeAnnounce(request, opts.MaxNumWant, opts.DefaultNumWant); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -126,7 +128,7 @@ func ParseScrape(r *http.Request, opts ParseOptions) (*bittorrent.ScrapeRequest,
|
|||
Params: qp,
|
||||
}
|
||||
|
||||
if err := opts.SanitizeScrape(request); err != nil {
|
||||
if err := bittorrent.SanitizeScrape(request, opts.MaxScrapeInfoHashes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,6 @@ func init() {
|
|||
prometheus.MustRegister(promResponseDurationMilliseconds)
|
||||
}
|
||||
|
||||
// ErrInvalidIP indicates an invalid IP.
|
||||
var ErrInvalidIP = bittorrent.ClientError("invalid IP")
|
||||
|
||||
var promResponseDurationMilliseconds = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "chihaya_udp_response_duration_milliseconds",
|
||||
|
@ -84,7 +81,7 @@ func (cfg Config) LogFields() log.Fields {
|
|||
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
||||
"maxNumWant": cfg.MaxNumWant,
|
||||
"defaultNumWant": cfg.DefaultNumWant,
|
||||
"maxScrapeInfohashes": cfg.MaxScrapeInfoHashes,
|
||||
"maxScrapeInfoHashes": cfg.MaxScrapeInfoHashes,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +314,7 @@ func (t *Frontend) handleRequest(r Request, w ResponseWriter) (actionName string
|
|||
req.AddressFamily = bittorrent.IPv6
|
||||
} else {
|
||||
log.Error("udp: invalid IP: neither v4 nor v6", log.Fields{"IP": r.IP})
|
||||
WriteError(w, txID, ErrInvalidIP)
|
||||
WriteError(w, txID, bittorrent.ErrInvalidIP)
|
||||
return
|
||||
}
|
||||
af = new(bittorrent.AddressFamily)
|
||||
|
|
|
@ -49,8 +49,10 @@ var (
|
|||
//
|
||||
// If AllowIPSpoofing is true, IPs provided via params will be used.
|
||||
type ParseOptions struct {
|
||||
AllowIPSpoofing bool `yaml:"allowIPSpoofing"`
|
||||
bittorrent.RequestSanitizer `yaml:",inline"`
|
||||
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
||||
MaxNumWant uint32 `yaml:"max_numwant"`
|
||||
DefaultNumWant uint32 `yaml:"default_numwant"`
|
||||
MaxScrapeInfoHashes uint32 `yaml:"max_scrape_infohashes"`
|
||||
}
|
||||
|
||||
// ParseAnnounce parses an AnnounceRequest from a UDP request.
|
||||
|
@ -117,7 +119,7 @@ func ParseAnnounce(r Request, v6 bool, opts ParseOptions) (*bittorrent.AnnounceR
|
|||
Params: params,
|
||||
}
|
||||
|
||||
if err := opts.SanitizeAnnounce(request); err != nil {
|
||||
if err := bittorrent.SanitizeAnnounce(request, opts.MaxNumWant, opts.DefaultNumWant); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -208,7 +210,7 @@ func ParseScrape(r Request, opts ParseOptions) (*bittorrent.ScrapeRequest, error
|
|||
|
||||
// Sanitize the request.
|
||||
request := &bittorrent.ScrapeRequest{InfoHashes: infohashes}
|
||||
if err := opts.SanitizeScrape(request); err != nil {
|
||||
if err := bittorrent.SanitizeScrape(request, opts.MaxScrapeInfoHashes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue