(partially tested) add scrape JWT validation

* remove `xorshift` package, add internal function in `varinterval`
* change `bittorrent.QueryParams` getters to search case insensitive keys
This commit is contained in:
Lawrence, Rendall
2022-08-25 18:31:48 +03:00
parent f5a58630db
commit 498779aeaf
9 changed files with 276 additions and 169 deletions
+29 -7
View File
@@ -3,14 +3,15 @@ package varinterval
import (
"context"
"encoding/binary"
"errors"
"fmt"
"math"
"sync"
"time"
"github.com/sot-tech/mochi/bittorrent"
"github.com/sot-tech/mochi/middleware"
"github.com/sot-tech/mochi/middleware/pkg/random"
"github.com/sot-tech/mochi/pkg/conf"
"github.com/sot-tech/mochi/storage"
)
@@ -79,14 +80,12 @@ type hook struct {
}
func (h *hook) HandleAnnounce(ctx context.Context, req *bittorrent.AnnounceRequest, resp *bittorrent.AnnounceResponse) (context.Context, error) {
s0, s1 := random.DeriveEntropyFromRequest(req)
// Generate a probability p < 1.0.
v, s0, s1 := random.Intn(s0, s1, 1<<24)
p := float32(v) / (1 << 24)
if h.cfg.ModifyResponseProbability == 1 || p < h.cfg.ModifyResponseProbability {
p, s0, s1 := xoroshiro128p(deriveEntropyFromRequest(req))
if float32(float64(p)/math.MaxUint64) < h.cfg.ModifyResponseProbability {
// Generate the increase delta.
v, _, _ = random.Intn(s0, s1, h.cfg.MaxIncreaseDelta)
add := time.Duration(v+1) * time.Second
v, _, _ := xoroshiro128p(s0, s1)
add := time.Duration(v%uint64(h.cfg.MaxIncreaseDelta)+1) * time.Second
resp.Interval += add
@@ -102,3 +101,26 @@ func (h *hook) HandleScrape(ctx context.Context, _ *bittorrent.ScrapeRequest, _
// Scrapes are not altered.
return ctx, nil
}
// deriveEntropyFromRequest generates 2*64 bits of pseudo random state from an
// bittorrent.AnnounceRequest.
//
// Calling deriveEntropyFromRequest multiple times yields the same values.
func deriveEntropyFromRequest(req *bittorrent.AnnounceRequest) (v0 uint64, v1 uint64) {
if len(req.InfoHash) >= bittorrent.InfoHashV1Len {
v0 = binary.BigEndian.Uint64([]byte(req.InfoHash[:8])) + binary.BigEndian.Uint64([]byte(req.InfoHash[8:16]))
}
v1 = binary.BigEndian.Uint64(req.ID[:8]) + binary.BigEndian.Uint64(req.ID[8:16])
return
}
// xoroshiro128p calculates predictable pseudorandom number
// with XOR/rotate/shift/rotate 128+ algorithm.
// see https://prng.di.unimi.it/xoroshiro128plus.c
func xoroshiro128p(s0, s1 uint64) (result, ns0, ns1 uint64) {
result = s0 + s1
s1 ^= s0
ns0 = ((s0 << 24) | (s0 >> 40)) ^ s1 ^ (s1 << 16) // rotl(s0, 24) ^ s1 ^ (s1 << 16)
ns1 = (s1 << 37) | (s1 >> 27) // rotl(s1, 37)
return
}
@@ -3,12 +3,15 @@ package varinterval
import (
"context"
"fmt"
"math/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/sot-tech/mochi/bittorrent"
"github.com/sot-tech/mochi/pkg/conf"
_ "github.com/sot-tech/mochi/pkg/randseed"
)
var configTests = []struct {
@@ -61,3 +64,13 @@ func TestHandleAnnounce(t *testing.T) {
require.True(t, resp.Interval > 0, "interval should have been increased")
require.True(t, resp.MinInterval > 0, "min_interval should have been increased")
}
func BenchmarkXORoShiRo128Plus(b *testing.B) {
s0, s1 := rand.Uint64(), rand.Uint64()
var v uint64
b.ResetTimer()
for i := 0; i < b.N; i++ {
v, s0, s1 = xoroshiro128p(s0, s1)
}
_, _, _ = v, s0, s1
}