A computed module says what its machine opens, so a hub can be filtered
The machine that most needed a firewall was the one that could not have one. A hub is dialled by every node at other sites and needs its port open; a machine that is not a hub dials out and needs nothing open. They are the same module, and `listens` in a manifest is one answer for every machine that runs it — so the machine a static answer gets wrong is the one facing the public internet. A generator can now say what it opens, in a second interface rather than a method on every generator: most have nothing to say here, and requiring an empty method of each would be a cost paid everywhere for one caller. The port is the one in the endpoint, which is where the interface takes its ListenPort from. One source, so a rule set cannot open a port the interface is not on. Open to everywhere and deliberately: a node at another site is not on the private network until this port lets it on, so restricting it to the mesh would be a rule that can never be satisfied by the thing it exists for. And a generator that cannot say is refused rather than read as silence. Closing a port on the evidence of a failure to look is how a machine is severed by a fault somewhere else — and the machine it would sever is the hub, whose only route to being fixed is the network it just closed.
This commit is contained in:
@@ -26,6 +26,22 @@ type Generator interface {
|
||||
Resources(node string) ([]map[string]any, bool, error)
|
||||
}
|
||||
|
||||
// OpensPorts is a generator that also says what its resources accept connections on.
|
||||
//
|
||||
// **Separate from Generator, because most generators have nothing to say here** and requiring an
|
||||
// empty method of each would be a cost paid everywhere for one caller.
|
||||
//
|
||||
// It exists because a static field cannot express this. A hub accepts connections from every node
|
||||
// at other sites; a machine that is not a hub dials out and needs nothing open — and they are the
|
||||
// same module. `listens` in a manifest is one answer for every machine that runs it, so the
|
||||
// machine that most needs filtering, the one facing the public internet, was the one whose rule
|
||||
// set would have closed its own overlay.
|
||||
type OpensPorts interface {
|
||||
// Listens is what this node accepts on because of what was computed for it. Nothing is the
|
||||
// ordinary answer: most machines running a computed module open no port at all.
|
||||
Listens(node string) ([]Listening, error)
|
||||
}
|
||||
|
||||
// Grant is one consumer's credential, on the machine that must create it.
|
||||
type Grant struct {
|
||||
// Provision is what was required.
|
||||
@@ -93,7 +109,11 @@ func (r Resolution) Declaration(with Rendering) ([]map[string]any, error) {
|
||||
|
||||
// Once, from every module's listens -- not per module. A module receiving only its own ports
|
||||
// would write a rule set that closed every other module on the machine.
|
||||
filtering := AsNftables(r.Filtering(), with.Mesh)
|
||||
rules, err := r.Filtering(with.Generators)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filtering := AsNftables(rules, with.Mesh)
|
||||
|
||||
var out []map[string]any
|
||||
for _, m := range r.Modules {
|
||||
|
||||
Reference in New Issue
Block a user