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
200 lines
8.5 KiB
Markdown
200 lines
8.5 KiB
Markdown
# 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`.
|
|
|
|
```hujson
|
|
{
|
|
"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:
|
|
|
|
```powershell
|
|
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)
|
|
|
|
```powershell
|
|
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
|
|
|
|
```powershell
|
|
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:
|
|
|
|
```bash
|
|
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`:
|
|
|
|
```bash
|
|
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
|
|
|
|
```powershell
|
|
"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.
|