Files
ROMFASTSQL/docs/acces-client-tailscale-ssh.md
Marius 7fce925349 feat(oracle): kit de instalare la client + corectarea lipsurilor din instalare
Blocul de instalare/migrare Oracle 21c XE, terminat si validat pe VM 302.

Kit de instalare (nou)

  scripts/build-client-kit.ps1 exporta CONTAFIN_ORACLE si FIRMANOUA de pe
  LXC 108 (PDB ROA2, nu ROA - ROA e productia ROA_CENTRAL), le aduce local
  prin cele trei hopuri container -> LXC -> host -> statie, le redenumeste la
  numele pe care le asteapta scripturile si le impacheteaza cu o copie a
  directorului roa-windows-setup. Citeste logul expdp si raporteaza cate
  firme are NOM_FIRME, ca sa nu plece din greseala datele unui client.

  roa-windows-setup/INSTALEAZA.cmd ruleaza pasii 01..08 fara "set /p", deci
  merge si prin SSH - RunAll.cmd nu poate fi rulat neinteractiv. Trateaza
  corect codul 5 de la pasul 03 si se opreste la prima eroare reala.

Corectii

  01-setup-database.ps1 nu mai scrie SQLNET.RECV_TIMEOUT / SEND_TIMEOUT in
  sqlnet.ora. Le hardcoda la 30 s, iar fisierul e citit si de impdp: in timpul
  unui import serverul poate lucra minute fara sa trimita un pachet, clientul
  murea cu ORA-12609 iar scriptul raporta esec pentru un import care se
  terminase cu bine pe server. Reprodus si reparat pe VM 302.

  01-setup-database.ps1: Step 4c optional (-ResetSystemPassword) care curata
  EXPIRED(GRACE) pe SYSTEM in CDB root; ALTER PROFILE opreste expirarile
  viitoare dar nu reseteaza un cont deja intrat in gratie.

  uninstall-roa.sql: retry la DROP USER dupa KILL SESSION, plus un bloc final
  de verdict care numara ce a ramas si iese cu ORA-20900 daca baza nu e
  curata. Pana acum toate sectiunile prindeau exceptiile in WHEN OTHERS si
  scriptul tiparea "UNINSTALL COMPLETE" chiar si cand un user supravietuise,
  iar instalarea urmatoare dadea ORA-31684 in lant. 99-uninstall-roa.ps1
  propaga codul de iesire.

  08-post-install-config.ps1: Step 7b seteaza SMTP_OUT_SERVER si ACL-ul de
  retea pentru CONTAFIN_ORACLE. UTL_MAIL se instala si primea EXECUTE, adica
  destul cat sa compileze, dar nu si cat sa trimita. Privilegiul resolve nu
  accepta interval de porturi (ORA-24244), deci se acorda separat de connect.

  07-verify-installation.ps1: sectiune noua care verifica prezenta lui
  FIRMANOUA.dmp in DMPDIR si o raporteaza ca eroare daca lipseste. Fara el,
  adaugarea unei firme noi pica in DBMS_DATAPUMP.ADD_FILE peste luni de la
  instalare, cand nimeni nu mai leaga eroarea de instalare.

  configure-profile.sql: antetul spune ca e unealta de remediere manuala, nu
  parte din flux; pas nou la final pentru CDB root.

Documentatie

  README-ul roa-windows-setup descrie acum explicit cele doua scenarii -
  instalare pe curat si migrare - de unde se iau DMP-urile sablon, si capcana
  ORA-12609. Handoff-urile de sesiune au fost sterse; ce era durabil in ele a
  intrat in README-uri si in docs/diagnostic-spatiu-clienti.md.

Validare pe VM 302: ciclu complet din kit, instalare pe curat, verificarea
finala "[OK] All checks passed!".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
2026-08-25 18:05:56 +03:00

8.5 KiB

Acces administrativ la un server de client prin Tailscale + SSH

De ce: pentru instalări/migrări Oracle la client avem nevoie de shell text pe serverul lui. RustDesk nu ajută — e sesiune grafică, nu se poate automatiza. Iar la mulți clienți nu se pot face forward-uri de porturi pe router. Tailscale rezolvă exact asta: nodul face doar conexiuni de ieșire (UDP 41641 pentru NAT traversal, cu cădere pe releu DERP peste 443), deci merge și în spatele CGNAT, fără nicio regulă pe router.

RustDesk rămâne util pentru bootstrap-ul de o singură dată — pașii de mai jos se execută manual, o dată, prin el.

Primul caz aplicat: VADECO — vadeco-server, Windows Server 2019 Standard, Tailscale 100.93.100.75 (2026-08-25).

Context conex: acces-ssh-chei-angajati.md (Bitvise pe chei, capcana LSA protection).


1. Tailscale pe serverul clientului

  1. Instalezi Tailscale, te loghezi cu contul ROMFAST.
  2. Run unattended — din tray → Preferences, sau tailscale up --unattended. Fără el, tailscaled pornește abia după ce cineva face login în Windows; pe un server la care nu se loghează nimeni, accesul e mort după fiecare reboot.
  3. Cere acordul clientului înainte — e VPN pe serverul lui.

2. Izolarea nodului: tag + ACL

Fără asta, serverul clientului intră în tailnet ca device obișnuit și vede toată infrastructura ROMFAST. Dacă e vreodată compromis, atacatorul sare mai departe.

Modelul Tailscale, pe scurt:

  • ACL-ul e default-deny: ce nu e permis explicit, e blocat. Nu scrii interdicții.
  • Regulile au direcție: src = cine deschide conexiunea, dst = cine o primește.
  • Fiecare device are o identitate: fie contul care l-a logat (user-owned), fie tag-ul. Aplicarea unui tag înlocuiește proprietatea contului, nu se adaugă la ea.
  • autogroup:member = conturile umane din tailnet. Un device tagged nu e member.

Politica

Admin console → Access controls. UI-ul nou are editor vizual (Definitions / Grants); fișierul HuJSON brut e la https://login.tailscale.com/admin/acls/file.

{
  "tagOwners": {
    "tag:client": ["autogroup:admin"],
  },

  "acls": [
    // device-urile noastre (ne-tagged) ajung oriunde
    { "action": "accept", "src": ["autogroup:member"], "dst": ["*:*"] },

    // NU exista nicio regula cu "src": ["tag:client"]
    // => serverul clientului nu poate initia nimic in tailnet
  ],
}

Obligatoriu: șterge regula implicită src: ["*"] → dst: ["*:*"]. Cât timp există, * include și tag:client și toată izolarea e degeaba.

Înainte de a șterge, verifică în Machines că niciun nod ROMFAST nu e deja tagged — ar rămâne fără acces.

Aplicarea tag-ului

Machines → nodul → ... → Edit ACL tags → tag:client.

Efecte: proprietatea trece la tag (dispare din „owned by you" — normal), iar expirarea cheii se dezactivează automat la device-urile tagged, deci nu mai trebuie dezactivată manual.

Verificare rapidă în tailscale status — nodul apare cu owner tagged-devices:

100.93.100.75   vadeco-server   tagged-devices   windows   -

Testul de izolare

Rulează aceeași comandă înainte și după aplicarea tag-ului, de pe serverul clientului:

Test-NetConnection 100.95.55.51 -Port 22    # 100.95.55.51 = LXC 171, are sshd pornit
  • înainte de tag: TcpTestSucceeded : True (nodul e încă member) — confirmă că testul e valid
  • după tag: TcpTestSucceeded : False (~20s până expiră) — confirmă izolarea

Nu folosi tailscale ping ca test de ACL. Lucrează sub filtrul de pachete și poate reuși chiar când ACL-ul blochează traficul real. Doar un test TCP pe un port concret spune adevărul.

Sensul invers (noi → client) se testează la punctul 4, cu serverul SSH pornit.

„Dacă nodul nu poate ajunge la noi, cum îmi răspunde SSH-ul?" — ACL-ul reglementează cine deschide o conexiune, nu direcția octeților. Sesiunea deschisă dinspre noi funcționează normal în ambele sensuri; clientul doar nu poate iniția el ceva spre tailnet.

3. Serverul SSH pe mașina clientului

Două variante; ambele merg, alege după context.

Bitvise SSH Server (consecvent cu restul clienților)

Control Panel → Easy settings:

  • Windows accounts → Administrator (sau alt cont din grupul Administrators) → Public keys → Import cheia publică. Shell access: terminal + exec.
  • Conturile virtuale rămân pentru tuneluri (la VADECO: romfast, vadeco, s2c pe 1521/80).

Capcana conturilor virtuale: implicit sunt mapate pe contul Windows bvssh_virtualusers, cu privilegii minime. Prin ele obții shell, dar Get-Service, Get-CimInstance și Get-PSDrive întorc gol — nu erori, ci nimic — și nu se poate instala Oracle. Simptom: whoami întoarce <host>\bvssh_virtualusers și verificarea de admin dă False.

Fie folosești un cont Windows real (mai simplu), fie mapezi contul virtual pe un cont admin din Advanced settings → Access control → grup → Windows account + parolă, plus setarea Elevation (fără ea, token filtrat de UAC și instalarea Oracle pică pe permisiuni obscure). Dezavantaj: parola de admin ajunge stocată în configul Bitvise.

Capcana LSA protection: pe Windows recent (~2025+) cu Bitvise < 9.51, autentificarea cu cheie pe conturi Windows eșuează (parola merge, cheia nu) — vezi acces-ssh-chei-angajati.md. Pe Server 2019 nu se aplică. Conturile virtuale nu sunt afectate niciodată.

OpenSSH nativ Windows (alternativă, fără licențiere)

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set-Service -Name sshd -StartupType Automatic
Start-Service sshd

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell `
  -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
  -PropertyType String -Force

$f = "$env:ProgramData\ssh\administrators_authorized_keys"
Set-Content -Path $f -Encoding ascii -Value 'ssh-ed25519 AAAA... comentariu'
icacls $f /inheritance:r /grant "*S-1-5-32-544:F" /grant "*S-1-5-18:F"

Restart-Service sshd
  • administrators_authorized_keys e fișierul corect pentru conturi admin (nu ~/.ssh).
  • ACL-ul de la icacls e obligatoriu: cu moștenire de permisiuni, sshd ignoră fișierul în tăcere și vezi doar „Permission denied". SID-urile evită problema pe Windows localizat.
  • -Encoding ascii intenționat — utf8 în PowerShell 5.1 scrie BOM, iar sshd nu digeră cheia.

Firewall

Set-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -RemoteAddress 100.64.0.0/10
# Bitvise:
Get-NetFirewallRule -DisplayName '*Bitvise*' | Set-NetFirewallRule -RemoteAddress 100.64.0.0/10

Restricția se face pe firewall, nu prin bind pe adresa 100.x în configul serverului SSH: la boot, interfața Tailscale urcă adesea după serviciu, bind-ul eșuează și serverul rămâne mort.

4. Testul de acceptanță

De pe orice device ROMFAST din tailnet:

ssh Administrator@100.93.100.75 "powershell -c (Get-Item 'C:\').FullName"

Pentru comenzi mai complexe, ghilimelele se pierd prin lanțul ssh → Bitvise → PowerShell. Folosește -EncodedCommand:

ENC=$(iconv -f UTF-8 -t UTF-16LE script.ps1 | base64 -w0)
ssh Administrator@100.93.100.75 "powershell -NoProfile -EncodedCommand $ENC"

Output-ul PowerShell prin exec vine cu antet #< CLIXML și un bloc <Objs Version=...> — se filtrează cu grep -v.

5. Verificare de mediu înainte de instalarea Oracle

"ADMIN  = $(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))"
"OS     = $((Get-CimInstance Win32_OperatingSystem).Caption)"
"RAM_GB = $([math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory/1GB,1))"
Get-Service | Where-Object {$_.Name -like 'Oracle*'} | Select-Object Name,Status,StartType
Get-PSDrive -PSProvider FileSystem | Select-Object Name,@{n='FreeGB';e={[math]::Round($_.Free/1GB,1)}}

ADMIN = True e condiția minimă — dacă e False, restul câmpurilor vin goale din lipsă de drepturi, nu pentru că lipsesc, și orice concluzie despre mașină e falsă.

Revocarea accesului

  1. Machines → nodul → Remove (îl scoate din tailnet complet); și/sau
  2. ștergerea cheii publice din contul de pe serverul SSH.

Pasul 1 e suficient și instantaneu — fără el, ștergerea cheii lasă nodul în rețea.