clarifying hidden service protocol chatter
This commit is contained in:
56
docs/hiddenservice-protocol.md
Normal file
56
docs/hiddenservice-protocol.md
Normal 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
|
||||
|
||||
```
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user