# SSH config Match blocks और agent approval

SSH की मंज़ूरी तभी सार्थक है, जब मंज़ूर किया गया connection वही हो जिसे SSH वास्तव में बनाएगा। बात सुनने में सीधी लगती है, लेकिन स्थिति तब बदल जाती है जब एजेंट `ssh prod` चलाता है, host alias किसी अलग `HostName` को चुनता है, कोई `Match` block remote user बदल देता है और `ProxyJump` session को ऐसे bastion से भेज देता है जिसका request में कहीं ज़िक्र नहीं था।

जब कोई व्यक्ति terminal देख रहा हो, तब SSH configuration की ज़्यादातर गलतियां संभाली जा सकती हैं। व्यक्ति अनजान host-key prompt देख लेता है, `root@...` पर ध्यान दे देता है या याद रखता है कि office network पर `prod` का मतलब कुछ और है। Autonomous agent में ऐसी शंका अपने-आप नहीं आती। वह दिए गए alias का इस्तेमाल करता है और config का ठीक-ठीक पालन करता है।

इसीलिए एजेंट को SSH access देने से पहले SSH config के `Match` blocks की security review ज़रूरी है। उद्देश्य aliases, bastions या conditional config पर रोक लगाना नहीं है। उद्देश्य यह सुनिश्चित करना है कि requested action, effective SSH configuration और इंसान द्वारा मंज़ूर किया गया connection एक ही चीज़ का वर्णन करें।

## Host alias input है, identity नहीं

`ssh app-prod` से यह पता नहीं चलता कि SSH कहां connect करेगा, कौन-सा account इस्तेमाल करेगा, कौन-सी key पेश करेगा या traffic पहले किसी दूसरी machine से गुज़रेगा। इससे केवल यह पता चलता है कि OpenSSH किस configuration argument से शुरुआत करेगा।

यह अंतर अक्सर धुंधला हो जाता है, क्योंकि aliases रोज़मर्रा के command-line काम को आसान बनाते हैं। `app-prod` जैसा छोटा नाम किसी खास user और nonstandard port वाले पूरी तरह qualified hostname की तुलना में टाइप करना आसान है। एजेंट को भी यह देना आसान है। लेकिन alias केवल एक handle है। उसका अर्थ उन सभी matching settings से बनता है जिन्हें SSH अपनी configuration files में पढ़ता है।

OpenSSH पहले command-line options, फिर user की `~/.ssh/config` और उसके बाद system-wide config पढ़ता है। ज़्यादातर single-value options के लिए SSH को जो पहली value मिलती है, वही इस्तेमाल होती है। OpenSSH के `ssh_config(5)` manual का व्यावहारिक नियम साफ़ है: specific declarations पहले और general defaults बाद में रखें। ऊपर की ओर रखा broad `Host *` block बाद में आने वाले अधिक सावधान conditional rule को चुपचाप निष्प्रभावी कर सकता है।

शुरुआत ऐसी inventory से करें जिसमें agent द्वारा इस्तेमाल किए जा सकने वाले हर alias को reviewer के लिए जांचने योग्य रूप में दर्ज किया गया हो:

| Alias | Resolved destination | Remote user | Route | Identity intent |
|---|---|---|---|---|
| `staging-api` | `api-01.staging.example.net` | `deploy` | direct | staging deploy identity |
| `prod-api` | `api-01.prod.example.net` | `deploy` | `prod-bastion` | production deploy identity |
| `prod-breakfix` | `api-01.prod.example.net` | `ops` | `prod-bastion` | incident-only identity |

Destination column में `production` न लिखें। वह actual target लिखें जिसे SSH इस्तेमाल करता है। `default user` न लिखें। `deploy`, `ubuntu`, `ec2-user` या server को मिलने वाला वास्तविक account लिखें। Route में jump host है, तो उसका नाम लिखें। अगर अलग-अलग networks पर alias अलग तरह से काम करता है, तो उसकी अपनी row होनी चाहिए, क्योंकि वह अलग effective connection है।

उपयोगी अंतर यह है: **alias configuration entry की पहचान करता है, जबकि destination remote endpoint की पहचान करता है**। दोनों को एक समझने से गलत approvals होती हैं। Reviewer agent को `staging-api` पर session खोलने की मंज़ूरी दे सकता है और फिर भी actual endpoint को लेकर गलत हो सकता है, क्योंकि alias में पुराना या conditional behavior मौजूद है।

इसी वजह से aliases को operational purpose बताना चाहिए, उसे छिपाना नहीं चाहिए। `prod-readonly`, `prod-deploy` और `prod-breakfix` reviewer को सही जगह रुककर सोचने पर मजबूर करते हैं। `prod` नाम का एक alias जो conditional blocks के ज़रिए users, keys और routes चुनता है, कुछ keystrokes बचाता है लेकिन review की स्थायी समस्या पैदा करता है।

## Match blocks executable connection logic हैं

`Match` block hosts के किसी group का label नहीं है। यह `ssh_config` का conditional section है, जो बदलता है कि कौन-से directives लागू होंगे। Conditions में requested host, original host, remote user, local user, canonicalization state, local network, requested command और `exec` command शामिल हो सकते हैं, जिसे SSH local shell के ज़रिए चलाता है।

यह शक्ति उपयोगी है। इसका अर्थ यह भी है कि config में ऐसा behavior हो सकता है जो केवल पास के `Host` alias को देखने पर दिखाई नहीं देता।

इस configuration पर ध्यान दें:

```sshconfig
Host prod-api
    HostName api-01.prod.example.net
    User deploy
    ProxyJump prod-bastion

Match originalhost prod-api user root
    IdentityFile ~/.ssh/breakfix_ed25519
    IdentitiesOnly yes
```

जो reviewer केवल `Host prod-api` block पढ़ता है, उसे `deploy` के रूप में deployment connection दिखाई देता है। अगर caller `ssh -l root prod-api` चलाता है, तो `Match originalhost prod-api user root` condition लागू हो सकती है। Identity setting प्रभावी होगी या नहीं, यह इस बात पर भी निर्भर करता है कि पहले identity settings कहां मिलीं और option कई values स्वीकार करता है या नहीं। महत्वपूर्ण बात सरल है: connection alias बदलने से नहीं, command-line user argument बदलने से बदल गया।

Agent use के लिए ऐसे `Match user` rules से बचें जो अधिक privileged identity या route देते हैं। यह तरीका व्यवस्थित लगता है, क्योंकि behavior को account name के आधार पर group किया जाता है। लेकिन calling tool इसे `-l`, `user@host` या generated command से आसानी से बदल सकता है। Intended `User` को purpose-specific alias में सीधे रखें।

अधिक सुरक्षित version हर intent को स्पष्ट बनाता है:

```sshconfig
Host prod-deploy
    HostName api-01.prod.example.net
    User deploy
    ProxyJump prod-bastion
    IdentityFile ~/.ssh/prod_deploy_ed25519
    IdentitiesOnly yes

Host prod-breakfix
    HostName api-01.prod.example.net
    User ops
    ProxyJump prod-bastion
    IdentityFile ~/.ssh/prod_breakfix_ed25519
    IdentitiesOnly yes
```

इससे privileged access harmless नहीं बनता। Requested connection साफ़ दिखाई देने लगता है। Agent को `prod-breakfix` चलाने के लिए अलग authorization चाहिए। केवल username बदलने से वह गलती से इस behavior में नहीं पहुंच सकता।

Agent-facing config में `Match exec` पर और भी कम भरोसा करें। SSH configuration evaluate करते समय यह local shell command चलाता है। Teams इसका इस्तेमाल network detection, inventory lookups या credential selection के लिए करती हैं। इससे SSH connection attempt local code path बन जाता है, जो environment dependencies पर निर्भर है। Human work के लिए यह flexibility चाहिए, तो ऐसे aliases को agent द्वारा चलाए जा सकने वाले set से बाहर रखें। Connection review के लिए किसी arbitrary shell command को reverse-engineer नहीं करना चाहिए।

## पहली matching value आपका exception निष्प्रभावी कर सकती है

SSH config की सबसे लगातार आने वाली गलती invalid stanza नहीं है। असली समस्या यह है कि valid stanza ऐसे broad rule के बाद रखी गई है जिसने option पहले ही set कर दिया।

मान लें कि production के लिए bastion ज़रूरी बनाने की कोशिश में developer यह लिखता है:

```sshconfig
Host *
    User deploy
    ProxyJump dev-bastion

Host prod-*
    ProxyJump prod-bastion
```

उम्मीद समझ में आती है: `prod-*` अधिक specific दिखता है, इसलिए उसे जीतना चाहिए। OpenSSH blocks को specificity के आधार पर sort नहीं करता। वह उन्हें file order में process करता है और कई directives के लिए पहली मिली value इस्तेमाल करता है। `prod-api` में `dev-bastion` ही रहेगा, क्योंकि पहले वाला `Host *` पहले ही `ProxyJump` दे चुका है।

Specific blocks पहले रखें:

```sshconfig
Host prod-*
    ProxyJump prod-bastion

Host *
    User deploy
    ServerAliveInterval 30
```

यह केवल style का मामला नहीं है। गलत bastion से होकर जाने वाला route session को गलत network path पर रख सकता है। Broad `User deploy` default किसी production alias को ऐसे account से authenticate करा सकता है जिसका उस host पर कोई काम नहीं है। Broad `IdentityFile intended key से पहले अनपेक्षित credential पेश कर सकता है।

First-value rule को जरूरत से ज्यादा सामान्य नियम न मानें। कुछ directives जानबूझकर multiple values स्वीकार करते हैं और `IdentityFile` इसका आम उदाहरण है। Configured identities उस set में जुड़ सकती हैं जिसे SSH consider करता है। इससे अलग समस्या पैदा होती है: narrow alias सही identity का नाम दे सकता है, फिर भी पहले की configuration या local SSH agent के ज़रिए दूसरी identities उपलब्ध रह सकती हैं।

Automated connections के लिए identity selection को स्पष्ट और उबाऊ रखें:

```sshconfig
Host prod-deploy
    HostName api-01.prod.example.net
    User deploy
    IdentityFile ~/.ssh/prod_deploy_ed25519
    IdentitiesOnly yes
    ProxyJump prod-bastion
```

`IdentitiesOnly yes` OpenSSH को बताता है कि वह केवल SSH configuration में configured या command line पर दी गई identities इस्तेमाल करे, न कि agent से उपलब्ध हर identity को आज़माता रहे। यह sloppy config को ठीक नहीं करता। लेकिन local agent में loaded unrelated key को accidental candidate बनने से रोकता है।

एक लोकप्रिय सलाह है कि सारे defaults `Host *` में रखें और केवल जरूरत पड़ने पर override करें। Keepalive intervals जैसी harmless settings के लिए यह ठीक है। लेकिन user selection, routes, identity files, ports, `ProxyCommand` और host rewriting के लिए यह खराब practice है। Authority को प्रभावित करने वाले defaults कम रखें। थोड़ी repetition उस स्थिति को समझाने से सस्ती है जिसमें agent सही machine तक गलत path से पहुंचा हो।

## ProxyJump एक और connection बनाता है, जिसकी समीक्षा ज़रूरी है

`ProxyJump` destination connection को केवल सजाता नहीं है। SSH पहले jump host से connect करता है और फिर उसी jump host से destination तक TCP forwarding path बनाता है। कई proxies को list करके क्रम से traverse किया जा सकता है। OpenSSH manual यह भी चेतावनी देता है कि destination-host configuration आम तौर पर jump hosts पर लागू नहीं होती।

यहीं reviews अक्सर विफल होती हैं। Config `prod-api` के लिए बहुत precise हो सकती है और `prod-bastion` के बारे में पूरी तरह अस्पष्ट।

```sshconfig
Host prod-api
    HostName 10.40.8.17
    User deploy
    ProxyJump prod-bastion

Host prod-bastion
    HostName bastion.prod.example.net
    User jump
    IdentityFile ~/.ssh/bastion_ed25519
    IdentitiesOnly yes
```

यह दो authentication decisions और दो host identities हैं:

1. SSH local client को `bastion.prod.example.net` पर `jump` के रूप में authenticate करता है।
2. Bastion TCP stream को `10.40.8.17` तक forward करता है।
3. SSH उसी stream के ज़रिए destination पर `deploy` के रूप में authenticate करता है।

Jump host की key, user, port और host-key record अलग हो सकती है। उसे wildcard alias या conditional block भी चुन सकता है, जिसे कोई इसलिए जांचता नहीं क्योंकि agent ने केवल `prod-api` request किया था।

हर hop की समीक्षा `ssh -G` से करें, केवल final alias की नहीं:

```sh
ssh -G prod-api | egrep '^(hostname|user|port|proxyjump|identityfile|identitiesonly) '
ssh -G prod-bastion | egrep '^(hostname|user|port|identityfile|identitiesonly) '
```

Output में हर line पर एक option होता है। एक स्वस्थ review में ऐसा रूप दिख सकता है:

```text
hostname api-01.prod.example.net
user deploy
port 22
proxyjump prod-bastion
identityfile ~/.ssh/prod_deploy_ed25519
identitiesonly yes
```

इसके बाद bastion को अलग से verify करें। अगर `prod-api` `edge-bastion,prod-bastion` जैसी comma-separated chain इस्तेमाल करता है, तो दोनों aliases के लिए command चलाएं। Chain कोई एक opaque route नहीं है। यह कई अलग SSH client configurations हैं।

`Host *` या `Host *.internal` जैसे wide pattern में generic jump route define न करें। इससे temporary hosts, staging environments और महीनों बाद जोड़े गए aliases भी पकड़ में आ जाते हैं। Jump route उन्हीं aliases में define करें जिन्हें उसकी ज़रूरत है। अगर कई production aliases को इसकी ज़रूरत है, तो production aliases के लिए reserved narrow pattern इस्तेमाल करें और उसे casually reuse न करें।

`ProxyCommand` भी जांचें। OpenSSH `ProxyJump` और `ProxyCommand` को competing options मानता है: जो पहले specify होता है, वह दूसरे की बाद की instances को प्रभावी होने से रोकता है। कोई config bastion का इस्तेमाल करती हुई दिख सकती है, लेकिन वास्तव में पहले वाला proxy command चल रहा हो सकता है। Reviewer को दोनों settings flag करनी चाहिए, क्योंकि दोनों network connection के origin और destination तक पहुंचने का तरीका बदलती हैं।

## User selection मंज़ूर की जा रही authority बदल देता है

Remote account requested action का हिस्सा है। `deploy@api-01.prod.example.net` और `ops@api-01.prod.example.net` एक ही server तक पहुंच सकते हैं, लेकिन दोनों की authority, shell profile, forced commands, sudo rights और audit trail अलग हो सकती है।

SSH remote user कई जगहों से ले सकता है: command में `user@host`, `ssh -l user host`, `User` directive या, अगर कुछ और उपलब्ध न हो, local username। केवल «कौन-सा host?» पूछने वाली config review अधूरी है।

जब agent का कोई defined job हो, तो user को pin करने वाले aliases इस्तेमाल करें:

```sshconfig
Host inventory-read
    HostName inventory.prod.example.net
    User inventory_ro
    IdentityFile ~/.ssh/inventory_ro_ed25519
    IdentitiesOnly yes

Host inventory-deploy
    HostName inventory.prod.example.net
    User deploy
    IdentityFile ~/.ssh/inventory_deploy_ed25519
    IdentitiesOnly yes
```

Agent को generic hostname न दें और यह न मानें कि prompt या wrapper उसे सही account तक सीमित रखेगा। Command generator `deploy@inventory.prod.example.net` की तरह ही आसानी से `ops@inventory.prod.example.net` भी बना सकता है। Config को authorized path आसान और privileged paths स्पष्ट रूप से अलग रखने चाहिए।

उन alternate forms की जांच करें जिन्हें कोई tool generate कर सकता है:

```sh
ssh -G inventory-read | grep '^user '
ssh -G -l ops inventory-read | grep '^user '
ssh -G ops@inventory-read | grep '^user '
```

अगर दूसरी या तीसरी command ऐसा account देती है जिसे agent को इस्तेमाल नहीं करना चाहिए, तो configuration को reviewed न मानें। Calling interface ठीक करें या उस alias को अलग करें। इन variants में से किसी एक के तहत `Match user` block भी सक्रिय हो सकता है, इसलिए visual inspection के बजाय explicit testing ज़रूरी है।

Teams को `root` access अलग नाम वाले emergency alias के लिए रखना चाहिए और उसे सामान्य agent permissions से बाहर रखना चाहिए। `User root` को `Match` condition के पीछे छिपाना उसे साफ़ लिखने से भी खराब है। Incident के समय condition ढूंढना पड़ेगा और caller कभी-कभी command-line parameter बदलकर उसे satisfy कर सकता है।

## IdentityFile केवल key path नियंत्रित नहीं करता

`IdentityFile` देखने में file-selection setting लगता है। व्यवहार में यह तय करता है कि SSH कौन-सा credential पेश कर सकता है और server किन remote authorization rules को evaluate करेगा।

एक आम failure ऐसा दिखता है:

```sshconfig
Host *
    IdentityFile ~/.ssh/id_ed25519

Host prod-*
    IdentityFile ~/.ssh/prod_ed25519
```

Operator सोचता है कि production `prod_ed25519` इस्तेमाल करेगा। SSH के candidate list में दोनों identity files हो सकती हैं, क्योंकि `IdentityFile` multiple entries स्वीकार करता है। अगर SSH agent में अतिरिक्त keys हैं और `IdentitiesOnly` मौजूद नहीं है, तो वे भी पेश की जा सकती हैं। कुछ servers repeated offers को जल्दी reject करते हैं और कुछ ऐसी unintended identity स्वीकार कर लेते हैं जो access दे देती है। दोनों में intent साफ़ नहीं रहता।

Agent-facing alias में एक credential purpose स्पष्ट होना चाहिए और offers सीमित होने चाहिए:

```sshconfig
Host reports-export
    HostName reports.prod.example.net
    User exporter
    IdentityFile ~/.ssh/reports_export_ed25519
    IdentitiesOnly yes
```

इसके बाद stanza पर भरोसा करने के बजाय effective configuration देखें:

```sh
ssh -G reports-export | grep '^identityfile '
ssh -G reports-export | grep '^identitiesonly '
```

एक से अधिक `identityfile` lines होना अपने-आप गलत नहीं है। Certificate-based setups और planned key rotation इसके उचित कारण हो सकते हैं। लेकिन सूची में दी गई हर identity उसी authority boundary से जुड़ी होनी चाहिए। अगर एक alias personal administrator key, पुरानी deployment key और production automation key, तीनों पेश कर सकता है, तो उसका authorization story साफ़ नहीं है।

इसे ठीक करने के लिए private keys को agent की files, environment, prompt या generated script में न रखें। इससे configuration ambiguity केवल credential exposure में बदलती है। Sallyport SSH keys को अपने encrypted vault में रखता है और अपने helper के ज़रिए SSH actions चलाता है, लेकिन वह अस्पष्ट SSH config को सही नहीं बना सकता। Operator द्वारा agent process को मंज़ूरी देने से पहले alias, route, user और identity intent फिर भी स्पष्ट होने चाहिए।

यही नियम key names पर भी लागू होता है। `~/.ssh/id_ed25519` जैसा path intended use के बारे में कुछ नहीं बताता। `prod_deploy_ed25519` बेहतर है, लेकिन config को पूरी बात फिर भी बतानी चाहिए: कौन-सा host group, कौन-सा user और कौन-सा route इसे इस्तेमाल करता है। File names review में मदद करते हैं, उसकी जगह नहीं लेते।

## Canonicalization से एक alias दो बार match कर सकता है

Hostname canonicalization उन कम दिखाई देने वाले तरीकों में से एक है जिनसे SSH configuration बदलती है। `CanonicalizeHostname yes` enabled होने पर OpenSSH unqualified name लेकर configured domain suffixes जोड़ सकता है, उसे resolve कर सकता है और फिर नए target name के साथ configuration को दोबारा process कर सकता है। `Match canonical` इस बाद वाले pass पर लागू होता है। `Match final` final parse मांगता है और उसी pass में match करता है। Canonicalization enabled होने पर canonical और final conditions साथ match होती हैं।

बड़े internal networks में यह उपयोगी हो सकता है। लेकिन इससे short alias conditional configuration trap बन सकता है।

```sshconfig
CanonicalizeHostname yes
CanonicalDomains corp.example.net

Host build
    User ci

Match canonical host *.prod.example.net
    ProxyJump prod-bastion
```

Caller `ssh build` चलाता है। पहले pass में `build` दिखाई देता है। अगर canonicalization इसे `build.prod.example.net` के रूप में resolve करती है, तो SSH configuration को फिर parse करता है और `Match canonical host *.prod.example.net` block production route set कर सकता है। Connection इसलिए नहीं बदला कि caller ने अलग alias मांगा था। यह DNS और दूसरे parsing pass के कारण बदला, जिसने बाद के rules को दिखने वाला host बदल दिया।

OpenSSH manual दो conditions के बीच अंतर बताता है, जिन्हें लोग अक्सर एक जैसा समझते हैं:

- `Match originalhost` caller द्वारा दिए गए host token की जांच करता है।
- `Match host` `HostName` substitution या canonicalization के बाद target की जांच करता है।

जब behavior को जानबूझकर named alias से बांधना हो, तो `originalhost` इस्तेमाल करें। जब behavior actual resolved destination पर निर्भर होना चाहिए, तो `host` इस्तेमाल करें। Privilege changes के लिए इनमें से किसी को भी casually न इस्तेमाल करें।

Bastions के साथ canonicalization का एक और महत्वपूर्ण पहलू है। `CanonicalizeHostname yes` आम तौर पर `ProxyCommand` या `ProxyJump` वाले connections पर लागू नहीं होता। `CanonicalizeHostname always` इसे proxied connections तक बढ़ाता है। इसका अर्थ है कि एक जैसे दिखने वाले दो aliases केवल इस वजह से अलग rewrite rules अपना सकते हैं कि उनमें से एक jump host इस्तेमाल करता है।

Agent permissions के लिए आम तौर पर सबसे आसान policy ही बेहतर है: agent को दिए जाने वाले aliases के लिए canonicalization बंद करें और explicit fully qualified `HostName` values इस्तेमाल करें। अगर environment में canonicalization ज़रूरी है, तो agent जिस exact network context में चलता है, उसमें हर allowed alias की जांच करें। यह न मानें कि short hostname home network, corporate network, VPN और office Wi-Fi पर एक ही तरह resolve होगा।

`Match localnetwork` भी यही चिंता पैदा करता है। OpenSSH document करता है कि local network address security-sensitive configuration के लिए भरोसेमंद नहीं है, खासकर DHCP-configured networks पर। Convenience settings के लिए यह ठीक है। इसका इस्तेमाल agent को अधिक privileged identity देने, bastion छोड़ने या production तक पहुंचने का निर्णय लेने के लिए न करें।

## Authorization से पहले connection render करें

SSH config को prose से testable रूप में बदलने का सबसे तेज़ तरीका `ssh -G` है। यह host और Match rules process करने के बाद SSH द्वारा इस्तेमाल की जाने वाली configuration print करता है और connection खोले बिना exit हो जाता है।

Agent जिस exact alias और arguments का इस्तेमाल करेगा, उन्हीं के साथ इसे चलाएं। केवल command का हाथ से साफ़ किया हुआ version test न करें।

```sh
ssh -G prod-deploy | egrep '^(hostname|user|port|proxyjump|proxycommand|identityfile|identitiesonly|canonicalizehostname) '
```

Serious review के लिए full output को उस repository में fixture के रूप में save करें जो automation का मालिक है। Intentionally named config file इस्तेमाल करें, ताकि test developer की personal settings को चुपचाप inherit न करे:

```sh
ssh -F ./agent-ssh-config -G prod-deploy > ./testdata/prod-deploy.effective
```

Config बदलने पर fixture की समीक्षा करें। उपयोगी diff `hostname`, `user`, `proxyjump` या identity list में बदलाव को approval flow तक पहुंचने से पहले पकड़ लेता है। Full-config diff में noise हो, फिर भी यह किसी pull request में pasted block पर भरोसा करने से बेहतर है।

`ssh -vvv` का इस्तेमाल तभी करें जब `ssh -G` expected values दिखाए। Verbose connection logs यह पुष्टि करने में मदद करते हैं कि SSH वास्तव में कौन-सी host keys और authentication methods आज़माता है, लेकिन इनमें configuration decisions network noise के साथ मिल जाते हैं। पहले `-G` इस सवाल का जवाब देता है, «यह config क्या कहती है?» Reachability troubleshoot करने से पहले आपको यही सवाल हल करना है।

Variations को जानबूझकर test करें:

```sh
ssh -F ./agent-ssh-config -G prod-deploy
ssh -F ./agent-ssh-config -G -l ops prod-deploy
ssh -F ./agent-ssh-config -G ops@prod-deploy
ssh -F ./agent-ssh-config -G prod-deploy.prod.example.net
```

परिणाम या तो expected authority boundary के भीतर रहने चाहिए या fail होने चाहिए। अगर user override account बदल देता है, fully qualified form bastion छोड़ देता है या canonicalization के बाद short name को अलग identity मिल जाती है, तो आपको बंद करने लायक configuration path मिल गया है।

Included files भी जांचें। `Include` visible `~/.ssh/config` को machine-generated, corporate या project-specific rules से भरी directory का केवल front door बना सकता है। उसी local account और config path से effective output test करें, जिसका इस्तेमाल agent करेगा। अपनी shell से test करते समय agent द्वारा किसी दूसरे account का इस्तेमाल करना certainty का झूठा एहसास देता है।

## Agent-facing SSH config छोटी और purpose-built रखें

Autonomous coding agent के लिए सबसे अच्छी SSH config आम तौर पर आपकी personal SSH config नहीं होती, भले ही उसमें कुछ comments जोड़ दिए जाएं। Personal configs में shortcuts, client exceptions, पुराने host aliases, local-network behavior, forwarded agents और कभी सुविधाजनक रही identities जमा होती रहती हैं। Agent को narrow connection catalog चाहिए।

एक dedicated config file बनाएं जिसमें केवल approved aliases और उनके लिए ज़रूरी supporting jump hosts हों। Agent या execution wrapper को `-F` के साथ उसी file की ओर point करें। हर alias का एक काम, explicit `HostName`, `User`, route और identity intent हो। Conditional logic तभी रखें जब आप दिखा सकें कि static alias से काम नहीं चल सकता।

एक छोटा example:

```sshconfig
Host prod-bastion
    HostName bastion.prod.example.net
    User jump
    IdentityFile ~/.ssh/prod_bastion_ed25519
    IdentitiesOnly yes

Host prod-deploy
    HostName api-01.prod.example.net
    User deploy
    ProxyJump prod-bastion
    IdentityFile ~/.ssh/prod_deploy_ed25519
    IdentitiesOnly yes

Host staging-deploy
    HostName api-01.staging.example.net
    User deploy
    IdentityFile ~/.ssh/staging_deploy_ed25519
    IdentitiesOnly yes
```

इसमें repetition है। अच्छी बात है। File reviewer को wildcard precedence और conditional state को मन ही मन execute किए बिना बता देती है कि हर connection का मतलब क्या है।

Dedicated config file को policy engine न समझें। Session शुरू होने के बाद कोई command सुरक्षित है या नहीं, यह साबित नहीं किया जा सकता। लेकिन transport connection को review के लिए पर्याप्त concrete बनाया जा सकता है: यह alias, यह endpoint, यह user, यह route, यह identity। यह उपयोगी सीमा है।

Sallyport की per-session authorization और activity records operators को human control point और agent actions का trail देते हैं, लेकिन action के पीछे के facts SSH config ही देती है। अगर `prod-deploy` कई network paths या accounts में बदल सकता है, तो configuration ने approval को पहले ही कम भरोसेमंद बना दिया है।

Agent को SSH alias इस्तेमाल करने देने से पहले उसे render करें, हर jump host की जांच करें और उन command-line variants को test करें जिन्हें agent बना सकता है। अगर effective connection आपको एक बार भी चौंकाता है, तो मान लें कि वह सबसे गलत समय पर किसी और को भी चौंकाएगा। Alias को तब तक ठीक करें, जब तक वह ऐसी approval की तरह न पढ़े जिसे इंसान सचमुच दे सके।
