clarifying hidden service protocol chatter

This commit is contained in:
херетик
2023-03-16 18:59:08 +00:00
parent 1b7ce9dea9
commit 0e62691366
4 changed files with 79 additions and 24 deletions

View File

@@ -0,0 +1,56 @@
# Hidden Service Message Protocol
## Creating a hidden service
```sequence
Note left of alice: return header A ->
Note left of alice: hidden service ->
alice-->bob: relay
bob-->charlie: relay
charlie-->dave: relay
note right of dave: <-introducer
note left of dave: return header A <-
dave-->charlie: gossip intro
dave-->eve: gossip intro
dave-->bob: gossip intro
```
## Requesting connection from introducer
```sequence
Note left of eve: return header B ->
eve-->dave: routing request
Note left of dave: -> return header A
dave-->charlie: relay
charlie-->bob: relay
bob-->alice: relay
note right of alice: <- return header B
alice-->bob: ready
note left of alice: return header C <-
bob-->charlie:
charlie-->eve:
note left of eve: return header C ->
```
## Request/Response Cycle
```sequence
note left of eve: return header C ->
Note left of eve: request message ->
Note right of eve: -> return header D
eve-->charlie: return onion
charlie-->bob: return onion
bob-->alice: return onion
Note right of alice: <- return header D
Note left of alice: reply message <-
note left of alice: return header E <-
alice-->bob: next request...
bob-->charlie:
note right of eve: <- return header E
charlie-->eve:
note left of eve: new request message ->
note left of eve: return header F ->
eve-->charlie: etc
charlie-->bob: etc
bob-->alice: and so on
```

View File

@@ -19,23 +19,19 @@ func init() { Register(HiddenRouteMagic, HiddenRoutePrototype) }
type HiddenRoute struct {
*pub.Key
recv *pub.Key
Cloak cloak.PubKey
Onion
}
func (o Skins) HiddenRoute(addr, recv *pub.Key) Skins {
func (o Skins) HiddenRoute(addr *pub.Key) Skins {
return append(o, &HiddenRoute{
Key: addr,
recv: recv,
Cloak: cloak.GetCloak(recv),
Key: addr,
})
}
func (x *HiddenRoute) Magic() string { return HiddenRouteMagic }
func (x *HiddenRoute) Encode(s *octet.Splice) (e error) {
s.Magic(HiddenRouteMagic).Pubkey(x.Key).Cloak(x.recv)
s.Magic(HiddenRouteMagic).Pubkey(x.Key)
if x.Onion != nil {
return x.Onion.Encode(s)
}
@@ -46,8 +42,7 @@ func (x *HiddenRoute) Decode(s *octet.Splice) (e error) {
if e = magic.TooShort(s.Remaining(), HiddenRouteLen-magic.Len,
HiddenRouteMagic); check(e) {
s.ReadPubkey(&x.Key).
ReadCloak(&x.Cloak)
s.ReadPubkey(&x.Key)
return
}
return
@@ -64,9 +59,9 @@ func (x *HiddenRoute) Handle(s *octet.Splice, p Onion,
return
}
func MakeHiddenRoute(addr, recv *pub.Key, header slice.Bytes,
func MakeHiddenRoute(addr *pub.Key, header slice.Bytes,
r *Routing) (o Skins) {
o = o.Triple(header).HiddenRoute(addr, recv).RoutingHeader(r)
o = o.Triple(header).HiddenRoute(addr).RoutingHeader(r)
return
}

View File

@@ -10,6 +10,7 @@ import (
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
"git-indra.lan/indra-labs/indra/pkg/engine/magic"
"git-indra.lan/indra-labs/indra/pkg/util/octet"
"git-indra.lan/indra-labs/indra/pkg/util/slice"
)
const (
@@ -22,7 +23,10 @@ func RoutePrototype() Onion { return &Route{} }
func init() { Register(RouteMagic, RoutePrototype) }
type Route struct {
HiddenService, Receiver *pub.Key
HiddenService *pub.Key
// Header is the 3 layer header to use with the following cipher and
// nonces to package the return message.
Header slice.Bytes
// Ciphers is a set of 3 symmetric ciphers that are to be used in their
// given order over the reply message from the service.
Ciphers [3]sha256.Hash
@@ -32,10 +36,11 @@ type Route struct {
Onion
}
func (o Skins) Route(key, receiver *pub.Key, point *ExitPoint) Skins {
func (o Skins) Route(key *pub.Key, header slice.Bytes,
point *ExitPoint) Skins {
return append(o, &Route{
HiddenService: key,
Receiver: receiver,
Header: header,
Ciphers: GenCiphers(point.Keys, point.ReturnPubs),
Nonces: point.Nonces,
Onion: NewTmpl(),
@@ -47,7 +52,7 @@ func (x *Route) Magic() string { return TmplMagic }
func (x *Route) Encode(s *octet.Splice) (e error) {
s.Magic(RouteMagic).
Pubkey(x.HiddenService).
Pubkey(x.Receiver).
Bytes(x.Header).
HashTriple(x.Ciphers).
IVTriple(x.Nonces)
if x.Onion != nil {
@@ -62,7 +67,7 @@ func (x *Route) Decode(s *octet.Splice) (e error) {
return
}
s.ReadPubkey(&x.HiddenService).
ReadPubkey(&x.Receiver).
ReadBytes(&x.Header).
ReadHashTriple(&x.Ciphers).
ReadIVTriple(&x.Nonces)
return
@@ -109,7 +114,7 @@ func (x *Route) Handle(s *octet.Splice, p Onion,
},
Nonces: [3]nonce.IV{n[0], n[1], n[2]},
}
hr := MakeHiddenRoute(hb.Intro.Key, x.Receiver, hb.Bytes, r)
hr := MakeHiddenRoute(hb.Intro.Key, hb.Bytes, r)
ob := hr.Assemble()
encoded := Encode(ob)
rb := FormatReply(hb.Bytes.ToBytes(), encoded.GetRange(-1, -1),
@@ -133,17 +138,17 @@ func (x *Route) Handle(s *octet.Splice, p Onion,
}
}
func MakeRoute(hs, recv *pub.Key, target *SessionData, s Circuit,
func MakeRoute(hs *pub.Key, header slice.Bytes, target *SessionData, s Circuit,
ks *signer.KeySet) Skins {
headers := GetHeaders(target, s, ks)
return Skins{}.
RoutingHeader(headers.Forward).
Route(hs, recv, headers.ExitPoint()).
Route(hs, header, headers.ExitPoint()).
RoutingHeader(headers.Return)
}
func (ng *Engine) SendRoute(hs, recv *pub.Key, target *SessionData,
hook Callback) {
func (ng *Engine) SendRoute(hs *pub.Key, header slice.Bytes,
target *SessionData, hook Callback) {
log.D.Ln("sending route", hs.ToBase32Abbreviated())
hops := StandardCircuit()
@@ -152,7 +157,7 @@ func (ng *Engine) SendRoute(hs, recv *pub.Key, target *SessionData,
se := ng.SelectHops(hops, s)
var c Circuit
copy(c[:], se)
o := MakeRoute(hs, recv, c[2], c, ng.KeySet)
o := MakeRoute(hs, header, c[2], c, ng.KeySet)
log.D.Ln("sending out route request onion")
res := ng.PostAcctOnion(o)
ng.SendWithOneHook(c[0].AddrPort, res, hook, ng.PendingResponses)

View File

@@ -88,7 +88,7 @@ func TestEngine_Route(t *testing.T) {
// peers := clients[1:]
delete(client.Introductions.KnownIntros, idPub.ToBytes())
rH := client.SessionManager.GetSessionsAtHop(2)
for i := range rH {
for _ = range rH {
wg.Add(1)
counter.Inc()
if len(rH) > 1 {
@@ -100,7 +100,6 @@ func TestEngine_Route(t *testing.T) {
func(id nonce.ID, k *pub.Bytes, b slice.Bytes) (e error) {
wg.Done()
counter.Dec()
log.I.Ln("success", i)
return
})
wg.Wait()