Acest document descrie configuratia activa din /home/nextgen/.ssh. Sursa versionata a proiectului este in /home/nextgen/projects/ssh-infrastructure; /home/nextgen/.ssh ramane runtime OpenSSH si nu contine repo-ul git. Ultima actualizare: 2026-05-15. Jurnalul istoric ssh-jump-attempts.md este obsolete si poate fi consultat doar din git.
/home/nextgen/.ssh/
config <- single-file generat din inventory/hosts.yaml
known_hosts
known_hosts.old
authorized_keys
keys/
id_ed25519
id_ed25519.pub
elastix-root.pub
.doc/
ssh-jump-architecture.md
~/.local/bin/
ssh
scp
sftp
Reguli:
~/projects/ssh-infrastructure; ~/.ssh ramane runtime OpenSSH.~/.ssh/keys.inventory/hosts.yaml, apoi generate in generated/*.conf.~/.ssh/config este instalat din generated/client.conf prin tools/deploy-local.sh; nu se editeaza manual.scripts/ in repo.~/.local/bin/ contine copiile executabile instalate de tools/deploy-local.sh; nu se editeaza manual.authorized_keys, known_hosts si config raman in radacina .ssh, pentru compatibilitate cu OpenSSH.j1-relay.sh, ssh-proxy.sh, ensure-ssh-agent-bridge.sh si ensure-ssh-jump.sh au fost eliminate; ssh-wrapper.sh ruleaza clientul SSH activ pe is-jumper, unde se afla cheia fizica.Scripturile sursa sunt in scripts/ in repo; ~/.local/bin/ contine copiile executabile instalate local.
| Comanda | Script | Mecanism |
|---|---|---|
ssh |
ssh-wrapper.sh |
parseaza args, rezolva hostul via ssh -G, construieste sesiunea nested |
scp |
scp-wrapper.sh |
apeleaza /usr/bin/scp -S ~/.local/bin/ssh — rutarea e delegata wrapper-ului ssh |
sftp |
sftp-wrapper.sh |
apeleaza /usr/bin/sftp -S ~/.local/bin/ssh — idem |
J1/J2; wrapperele locale nu reproduc algoritmi, KEX, cipher-uri sau OPENSSL_CONF.~/.local/bin inaintea /usr/bin, comenzile ssh/scp/sftp folosesc automat aceste wrappers.192.168.2.0/24 — rețea locală de birou
is-toltec (workstation-ul local)
is-jumper 192.168.2.100 (gardian cheie + client VPN)
10.253.51.0/24 — rețea internă companie (acces via VPN de pe is-jumper)
J1 10.253.51.50:25904
J2 10.253.51.52:25904
hosturi finale (voip, porta, radius etc.)
is-jumper (192.168.2.100) este pe rețeaua locală de birou — accesibil direct din is-toltec, fără VPN. Este un client VPN (nu server): prin el se obține acces la 10.253.51.0/24. Este gardianul cheii fizice (card RSA 4096) deoarece deservește mai mulți utilizatori din 192.168.2.0/24.
Cheia fizică (cardul) este montată exclusiv pe is-jumper și expusă prin GPG agent la /run/user/0/gnupg/S.gpg-agent.ssh. Wrapper-ul nu mai forwardează acest socket pe mașina locală; în schimb intră pe is-jumper, setează SSH_AUTH_SOCK la socketul local de acolo și rulează de pe is-jumper clientul SSH către J1/J2/j1/j2.
Calea standard (VPN activ, J1):
local
-> is-jumper (192.168.2.100, executor SSH + cheie fizica)
-> J1 (10.253.51.50:25904)
-> host final
Calea publică (urgențe, fără rută VPN, j1/j2):
local
-> is-jumper (192.168.2.100, executor SSH + cheie fizica)
-> j1.next-gen.ro:25904
-> host final
Sesiuni interactive pe J1/J2:
local -> is-jumper -> J1
local -> is-jumper -> J2
Nu mai exista bridge local de agent (/tmp/is-jumper-agent.sock). Cheia fizica ramane folosita local pe is-jumper.
Jumps disponibile via flaguri wrapper:
| Flag | Jump | Rută | Când |
|---|---|---|---|
implicit / -J1 |
J1 (10.253.51.50) | client SSH rulat pe is-jumper | standard |
-J2 |
J2 (10.253.51.52) | client SSH rulat pe is-jumper | failover VPN |
-j1 |
j1.next-gen.ro | client SSH rulat pe is-jumper | urgențe |
-j2 |
j2.next-gen.ro | client SSH rulat pe is-jumper | urgențe |
Parseaza argumentele ssh, rezolva hostul via ssh -G, construieste sesiunea nested activa pe is-jumper:
exec /usr/bin/ssh is-jumper "SSH_AUTH_SOCK=/run/user/0/gnupg/S.gpg-agent.ssh ssh -A <jump_host> '<final_ssh_cmd>'"
Bypass automat (pass-through direct) pentru:
- is-jumper / 192.168.2.100
- Flaguri de interogare: -G, -Q, -V, --help
Pentru J1/J2/j1/j2, wrapper-ul conecteaza intai local la is-jumper, apoi ruleaza acolo ssh -A cu SSH_AUTH_SOCK=/run/user/0/gnupg/S.gpg-agent.ssh. Pentru hosturile finale, comanda de pe jump ruleaza inca un ssh catre hostul final. Pentru scp/sftp, wrapper-ul pastreaza forma de subsystem -s ... sftp.
Wrappers subtiri care injecteaza -S ~/.local/bin/ssh la apelul sistemului:
/usr/bin/scp -S ~/.local/bin/ssh "$@"
/usr/bin/sftp -S ~/.local/bin/ssh "$@"
Rutarea este delegata integral catre ssh-wrapper.sh; scp/sftp raman transparente pentru utilizator.
Nu mai exista scripturi active bazate pe Python, ProxyJump sau port-forwarding externe; vechiul helper Python a fost eliminat dupa ce a fost semnalat de Sentinel.
~/.ssh/config este un single-file generat din inventory/hosts.yaml:
# Generated by tools/generate-configs.py.
# Do not edit this file directly; edit inventory/hosts.yaml.
Generatorul produce:
| Fisier | Destinatie | Rol |
|---|---|---|
generated/client.conf |
client local | config runtime pentru ~/.ssh/config |
generated/is-jumper.conf |
is-jumper | config pentru jump aliases |
generated/j1.conf |
J1 | hosturi finale |
generated/j2.conf |
J2 | hosturi finale |
Reguli de configurare:
HostName, User si Port;HostName numele
canonic deja cunoscut pe jump, iar IP-ul ramane alias pentru autocomplete;is-jumper defineste si cheia locala de acces (IdentityFile, IdentitiesOnly);is-jumper -> J1 implicit;inventory/hosts.yaml;generated/j1.conf si generated/j2.conf mostenesc blocul global company-managed
si omit User/Port cand toate aliasurile unui host sunt deja acoperite de
regulile Match Host de pe jump;generated/j1.conf si generated/j2.conf nu mai includ hosturile care folosesc
doar defaulturi mostenite; raman doar override-urile efective si exceptiile
per-pattern care trebuie pastrate pe jump;generated/j1.conf si generated/j2.conf sunt generate fara comentarii,
doar cu stanza-urile SSH necesare;Aliasuri principale:
| Alias | Rol | Rutare |
|---|---|---|
is-jumper |
VPN gateway + gardian cheie fizica | direct (IP 192.168.2.100) |
J1, J2 |
jump hosts, login interactiv | wrapper prin is-jumper |
voip-prov, voip-prov-root |
host VoIP provider | wrapper nested prin J1 |
porta-sip, porta-web, porta-db, porta-configurator |
PortaOne MR30 | wrapper nested prin J1 |
elastix |
host vechi | wrapper nested prin J1 |
*.radius-db, *.radius-pppoe |
baze Radius regionale | wrapper nested prin J1 |
J1 si J2 nu mai folosesc ProxyJump, IdentityAgent sau RemoteCommand in configul local; wrapper-ul orchestreaza explicit conexiunea prin is-jumper.
Aliasuri PortaOne:
porta-sip, p12-sip, p12, p12.voip.ro -> 193.16.148.4porta-web, porta-api, porta-slave, porta7, telefonie.next-gen.ro -> 193.16.148.7porta-db, porta-master, porta1 -> 193.16.148.11porta-configurator, porta-config -> 193.16.148.13Aceste hosturi folosesc ruta nested din wrapper; eventualele optiuni de compatibilitate ale hop-ului final sunt asigurate pe J1/J2.
Verificare configuratie fara conectare:
ssh -G is-jumper | grep -E '^(hostname|user|identityfile|identitiesonly)'
ssh -G porta-db | grep -E '^(hostname|user|port)'
ssh -G falticeni.radius-db | grep -E '^(hostname|user|port|connecttimeout)'
Verificare read-only cu conectare:
ssh porta-db hostname
ssh porta-sip 'service porta-sip status'
ssh voip-prov hostname
scp porta-db:/etc/hosts /tmp/test-scp
sftp porta-db <<< 'ls /'
~/.ssh/keys si seteaza permisiuni 600 pentru cheia privata.inventory/hosts.yaml, ruleaza generatorul si apoi tools/deploy-local.sh.inventory/hosts.yaml.scripts/ in repo si lasa tools/deploy-local.sh sa il instaleze in ~/.local/bin/.ProxyJump, IdentityAgent /tmp/is-jumper-agent.sock, helperul Python sau port-forwarding per-host.ForwardAgent yes pe hosturile finale fara un motiv explicit.ssh -G <alias> si cel putin un alias read-only (ssh porta-db hostname).