38 lines
1.6 KiB
Go
38 lines
1.6 KiB
Go
package keymgr
|
|
|
|
import "ssh-access-tui/internal/model"
|
|
|
|
// AllocatedForward is a model.Forward together with the local port it will
|
|
// be bound to on the user's machine.
|
|
type AllocatedForward struct {
|
|
model.Forward
|
|
LocalPort int
|
|
}
|
|
|
|
// localPortBase is where every local port is handed out from. Forwards are
|
|
// never given a local port equal to their remote port: many remote ports
|
|
// worth forwarding are privileged (< 1024 — ssh's own 22 above all), and
|
|
// binding a listener on a privileged local port requires admin/root rights
|
|
// the end user does not have and should not need. Even for unprivileged
|
|
// remote ports, always starting from a fixed high range keeps assignment
|
|
// simple and collision-free without a "does this port happen to be free
|
|
// locally" special case.
|
|
const localPortBase = 20000
|
|
|
|
// AllocateLocalPorts assigns every forward a local port, all of which the
|
|
// user opens at once over a single ssh connection (one LocalForward line
|
|
// per forward — see RenderClientConfig). Ports are handed out sequentially
|
|
// from localPortBase, so many forwards sharing the same remote port (e.g.
|
|
// port 22 repeated across ten hosts) each still get a distinct, unprivileged
|
|
// local port. Assignment is a pure function of the input order, so
|
|
// re-exporting an unchanged host list reproduces the same local ports.
|
|
func AllocateLocalPorts(forwards []model.Forward) []AllocatedForward {
|
|
next := localPortBase
|
|
out := make([]AllocatedForward, 0, len(forwards))
|
|
for _, f := range forwards {
|
|
out = append(out, AllocatedForward{Forward: f, LocalPort: next})
|
|
next++
|
|
}
|
|
return out
|
|
}
|