6 पॉइंट द्वारा GN⁺ 2023-08-24 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • SSH सिर्फ remote access से आगे बढ़कर port forwarding, jump host, config files, और key management तक को साथ में संभालने वाला टूल है, और web server के उदाहरण RDP·SQL जैसी दूसरी services पर भी वैसे ही लागू होते हैं
  • local·remote·dynamic port forwarding क्रमशः -L, -R, -D से सेट होते हैं, और मुख्य फर्क यह है कि port किस तरफ खुलता है और traffic किस दिशा में बहता है
  • जिन networks में direct access बंद हो, वहाँ -J jump host और ProxyJump से कई SSH hop जोड़कर destination तक पहुँचा जा सकता है
  • ssh-agent और -A agent forwarding remote host पर भी local keys इस्तेमाल करने देते हैं, जो सुविधाजनक है, लेकिन agent के दुरुपयोग से जुड़ी security risk पहले समझनी चाहिए
  • ~/.ssh/config, ssh-copy-id, ssh-keygen, और SSH console के ~?·~C को साथ इस्तेमाल करने पर बार-बार options टाइप करने की ज़रूरत कम होती है, session के दौरान forwarding जोड़ना, public key deploy करना, और key बनाना·जाँचना आसान हो जाता है

SSH port forwarding को समझने के लिए ज़रूरी आधार

  • SSH port forwarding को सिर्फ diagram से समझना मुश्किल हो सकता है, इसलिए असली commands और network scenarios को साथ देखकर समझना आसान होता है
  • उदाहरण web server access पर आधारित हैं, लेकिन यही तरीका RDP, SQL जैसी लगभग सभी services पर लागू किया जा सकता है
  • बार-बार इस्तेमाल होने वाले options का मतलब यह है
    • -N: remote server पर कोई command execute नहीं करता और shell भी नहीं खोलता
    • -f: SSH को background में भेज देता है
    • root@host: tunnel बनाने वाले user और host से login करता है

local port forwarding -L

  • local port forwarding local machine के port को remote server के port तक forward करता है
  • उदाहरण स्थिति
    • internal-web.int एक web page host करता है, जिस तक सिर्फ loopback interface से पहुँचा जा सकता है
    • campfire.int से internal-web.int पर SSH access संभव है
    • लक्ष्य है campfire.int के local port के ज़रिए internal-web.int के web server तक पहुँचना
  • इस्तेमाल की command
    • ssh -N -f -L 1337:127.0.0.1:80 root@internal-web.int
  • option का अर्थ
    • -L: local forwarding निर्दिष्ट करता है
    • 1337:127.0.0.1:80: local port 1337 को remote के 127.0.0.1:80 से bind करता है
  • tunnel बनने के बाद campfire.int पर local port 1337 को request भेजकर internal-web.int के port 80 से interact किया जा सकता है
  • याद रखने की बात: -L में local port address के बाएँ तरफ आता है

remote port forwarding -R

  • remote port forwarding local पर उपलब्ध port को remote server के port के रूप में expose करता है
  • उदाहरण स्थिति
    • internal-web.int एक web page host करता है, जिस तक सिर्फ loopback से पहुँचा जा सकता है
    • firewall की वजह से campfire.int सीधे internal-web.int तक नहीं पहुँच सकता
    • vuln-server.int तक campfire.int और internal-web.int दोनों से पहुँचा जा सकता है
  • इस्तेमाल की command
    • ssh -N -f -R 3000:127.0.0.1:80 root@vuln-server.int
  • option का अर्थ
    • -R: remote forwarding निर्दिष्ट करता है
    • 3000:127.0.0.1:80: vuln-server.int के port 3000 को local के 127.0.0.1:80 से bind करता है
  • इसके बाद vuln-server.int:3000 पर curl request भेजने से internal-web.int के port 80 पर चल रहे internal web page तक पहुँचा जा सकता है
  • याद रखने की बात: -R में local port address के दाएँ तरफ आता है

dynamic port forwarding -D और SOCKS proxy

  • dynamic port forwarding -D option से SOCKS proxy बनाता है और traffic को SSH relay के ज़रिए भेजता है
  • उदाहरण स्थिति
    • internal-web.int ऐसा web application host करता है, जिस तक सिर्फ internal network से पहुँचा जा सकता है
    • vuln-server.int उसी internal network में है और internal-web.int तक पहुँच सकता है
    • लक्ष्य है campfire.int से vuln-server.int के ज़रिए traffic को proxy करना
  • /etc/proxychains.conf की setting SSH command के port से मेल खानी चाहिए
    • socks5: proxychains को SOCKS5 इस्तेमाल करने देता है
    • 127.0.0.1: localhost का उपयोग करता है
    • 8080: यह SSH -D में दिए गए port से मेल खाना चाहिए
  • इस्तेमाल की command
    • ssh -N -f -D 8080 root@vuln-server.int
  • forwarding बनने के बाद socks5 127.0.0.1 8080 सेट करने पर proxychains curl 192.168.1.185 से internal web page तक पहुँचा जा सकता है
  • SOCKS के ज़रिए DNS हर environment में ठीक से काम नहीं कर सकता, इसलिए उदाहरण में hostname की जगह IP address इस्तेमाल किया गया है
  • Firefox में भी manual proxy settings के ज़रिए SOCKS proxy इस्तेमाल किया जा सकता है
    • path: Settings → Privacy & Security → Network Settings
    • Manual proxy configuration चुनें
    • “Proxy DNS when using SOCKS V5” को check करें
    • SOCKS host को 127.0.0.1 और port को 8080 पर सेट करें

jump host -J

  • jump host कई SSH relay से गुजरते हुए ऐसे destination तक पहुँचने देता है, जहाँ current host से direct access संभव नहीं है
  • उदाहरण chain है campfire.intvuln-server.intinternal-web.intdns.int
  • इस्तेमाल की command
    • ssh -J root@vuln-server.int,root@internal-web.int root@dns.int
  • कई jump targets को comma से अलग किया जाता है

agent forwarding -A

  • ssh-agent local machine पर ssh-add <private_key_file> से private key या ID जोड़ने देता है
  • जोड़ी गई keys को ssh-add -l से देखा जा सकता है
  • ssh-agent में key जोड़ने के बाद पासवर्ड फिर से डाले बिना उसी key से SSH login किया जा सकता है, इसलिए यह लोगों और service accounts दोनों के लिए उपयोगी है
  • -A agent forwarding login की गई remote machine पर भी local agent की keys इस्तेमाल करने देता है
  • इस्तेमाल से पहले security risk समझने के लिए Zero Effort Private Key Compromise: Abusing SSH-Agent for Lateral Movement देखें
  • उदाहरण command
    • ssh -A -J root@vuln-server.int root@internal-web.int
  • यह command vuln-server.int के रास्ते internal-web.int पर connect करते समय campfire.int के local SSH agent में मौजूद keys इस्तेमाल करने देती है
  • इसके बाद internal-web.int पर ssh root@dns.int चलाने पर private key अलग से बताने या credentials डालने की ज़रूरत नहीं होती

TTY command allocation -t

  • -t option remote server पर interactive command जल्दी चलाने में उपयोगी है
  • उदाहरण के तौर पर Vim या top जैसी commands, जिन्हें TTY चाहिए
  • इस्तेमाल की command
    • ssh root@internal-web.int -t top
  • इसे चलाने पर remote server पर top command सहित एक TTY मिल जाता है

-g: local forwarding port को बाहरी hosts के लिए खोलना

  • -g option remote hosts को local forwarded port से connect होने देता है
  • यह local port forwarding -L जैसा है, लेकिन फर्क यह है कि इस “local” port को बाहरी machines भी इस्तेमाल कर सकती हैं
  • उदाहरण स्थिति
    • vuln-server.int पर shell access है
    • लक्ष्य है vuln-server.int के port 2222 पर आने वाले connections को internal-web.int के port 22 तक proxy करना
  • इस्तेमाल की command
    • ssh -N -f -g -L 2222:localhost:22 root@internal-web.int
  • option का अर्थ
    • -g: remote hosts को local forwarded port से connect होने देता है
    • -L: local forwarding निर्दिष्ट करता है
  • vuln-server.int के port 2222 पर SSH से connect करने पर भी असली shell internal-web.int पर ही होगा

SSH console ~? और session के दौरान forwarding

  • SSH console एक छिपा हुआ feature है, जिससे remote system से सीधे interact किए बिना SSH को खुद control किया जा सकता है
  • shell खराब हो जाने पर या SSH session को ही control करना हो, तब यह उपयोगी है
  • help console ~? से खोला जा सकता है
  • उपयोगी options
    • ~.: मौजूदा SSH session को बंद करता है
    • ~C: SSH console खोलता है, जहाँ forwarding options जोड़े जा सकते हैं
  • अगर आप पहले से सामान्य ssh command से vuln-server.int में login हैं, तब भी ~C दबाकर -D 8080 डालने पर वही session dynamic forwarding session की तरह इस्तेमाल किया जा सकता है
  • अगर campfire.int पर /etc/proxychains.conf port 8080 के लिए configured है, तो proxychains का उपयोग ऐसे किया जा सकता है जैसे शुरुआत से ssh -D चलाया गया हो

SSH config file ~/.ssh/config

  • SSH config file ~/.ssh/config में होती है और बार-बार टाइप किए जाने वाले SSH options को सहेजकर समय बचाती है
  • SSH connect करते समय इस file को parse करता है, और अगर target के लिए मेल खाता host config हो तो उसी के options इस्तेमाल करता है
  • command-line arguments config file पर प्राथमिकता रखते हैं
    • उदाहरण के लिए, अगर config file में internal-web.int के लिए user root दिया गया हो, तब भी ssh graham@internal-web.int चलाने पर login की कोशिश graham के रूप में होगी
  • basic config example
# You can put comments with a `#` at the beginning of the line only.
host internal-web.int
    User root
    IdentityFile /home/smores/ssh_agent/internal-web-no-pw
    Port 2222
  • ssh internal-web.int चलाने पर processing flow
    • command-line के internal-web.int को ~/.ssh/config के host internal-web.int से match किया जाता है
    • match होने पर command-line में न दिए गए options config file से लिए जाते हैं
    • match न होने पर सिर्फ command-line में दिए गए options इस्तेमाल होते हैं

अक्सर इस्तेमाल होने वाले SSH config keywords

  • IdentityFile /path/to/private_key
    • host के लिए इस्तेमाल होने वाली private key निर्दिष्ट करता है
    • यह ssh -i जैसा ही है
  • ForwardAgent
  • ProxyJump root@internal-web.int
    • traffic को proxy करने वाला server निर्दिष्ट करता है
    • यह -J option जैसा ही है
    • उदाहरण में यह दिखाया गया है कि traffic उस host से गुज़रता है, क्योंकि पहले vuln-server.int authentication माँगता है
  • Match
    • conditions के आधार पर SSH config keywords लागू करता है
    • उदाहरण में अगर export | grep PROXYME=TRUE command का exit code 0 हो, तो Match block के नीचे वाला ProxyJump इस्तेमाल होता है
    • अगर PROXYME environment variable न हो, तो सिर्फ सामान्य host internal-web.int block इस्तेमाल होता है
    • export PROXYME=TRUE सेट करने के बाद वही ssh internal-web.int चलाने पर vuln-server.int authentication के बाद internal-web.int shell मिलता है
  • scp और कुछ SSH-आधारित utilities भी आमतौर पर SSH config इस्तेमाल कर सकती हैं
    • जिन environments में यह अपने-आप न हो, वहाँ -F ~/.ssh/config देकर इसे explicitly बताया जा सकता है

public key copy ssh-copy-id

  • ssh-copy-id public key को server पर जल्दी upload करने वाली एक छोटी utility है
  • इस्तेमाल की command
    • ssh-copy-id -i internal-web root@internal-web.int
  • option का अर्थ
    • -i internal-web: server authentication के लिए इस्तेमाल होने वाली private key का नाम निर्दिष्ट करता है
    • root@internal-web.int: वह server निर्दिष्ट करता है जहाँ public key upload करनी है

key generation और inspection ssh-keygen

  • ssh-keygen private key और public key की जोड़ी बनाने वाली utility है
  • आमतौर पर -b option से बड़ा key size निर्दिष्ट करना recommend किया जाता है
  • उदाहरण environment में default key size 3072 था
  • default algorithm RSA है, लेकिन -t flag से दूसरा algorithm चुना जा सकता है
    • उदाहरण: ssh-keygen -t ecdsa -b 521
  • key का fingerprint और byte size इस command से देखा जा सकता है
    • ssh-keygen -lf <file-name>

1 टिप्पणियां

 
GN⁺ 2023-08-24
Hacker News की टिप्पणियां
  • इसमें एक हैरान कर देने वाला सरल directive छूट गया है: sshd_config में AuthorizedKeysCommand /usr/bin/php /etc/ssh/auth.php %u जैसा सेट करें, और script में GitHub से https://github.com/{$user}.keys fetch कर लें
    बेशक यह production-quality code नहीं है, लेकिन मूल बात दिखा देता है
    GitHub organization/group की membership जांचने के बाद, अगर user मौजूद है और nss-ato जैसी किसी चीज़ से mapped है, तो server login allow किया जा सकता है
    लोगों को onboard/offboard करते समय सिर्फ GitHub group में add/delete करके machines का access देना या वापस लेना संभव है, जिससे झंझट कम होता है

    • Amazon Linux भी कुछ ऐसा ही करता है, लेकिन शायद production-quality होने की वजह से कहीं ज्यादा जटिल है
      Amazon Linux 2 और उससे नीचे में authorized_keys file की individual key format check करने के लिए openssl command line call की जाती है, लेकिन यह RSA पर hardcoded है, इसलिए OpenSSH version ed25519 support करने के बावजूद Amazon Linux 2 host पर ed25519 से authenticate नहीं किया जा सकता था
      Theory में यह एक अच्छा feature¹ enable करता है, इसलिए ठीक लगता है, लेकिन practice में यह उन लोगों के लिए भी basic functionality तोड़ देता है जो वह feature इस्तेमाल नहीं करते, जिससे Amazon Linux पर भरोसा कम होता है
      पहली बार जब मुझे यह problem मिली, मैं एक cloud-first DevOps colleague की machine में SSH करने की कोशिश कर रहा था, और मेरे पास direct access नहीं था, इसलिए diagnose करना मुश्किल था
      वह AWS तो अच्छी तरह जानता था, लेकिन Linux कम जानता था, इसलिए उसे पता नहीं था कि कहां देखना है; उसने Amazon Linux इसलिए चुना था क्योंकि यह cloud platform owner का बनाया distro है और उसे लगा था कि यह “more compatible” होगा, लेकिन यहां “more compatible” का मतलब असल में “अधिक बेवकूफी भरे surprises” निकला
      ¹ https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-...
    • ऐसी चीजें देखकर network side में होना खलता है
      “network ठीक से काम नहीं कर रहा” ही job scope है, इसलिए ऐसे शानदार features छूट जाते हैं
    • इस use case के लिए इसके बजाय SSH certificates इस्तेमाल करना बेहतर है
  • शायद बहुत लोगों को यह नहीं पता कि OpenSSH config parser duplicate directives को ignore करता है, और same directive में से सिर्फ पहला effective होता है
    आम तौर पर config parsers या rule engines में बाद में आया directive पहले वाले को overwrite करता है, इसलिए यह काफी counterintuitive है
    यह मामूली लग सकता है, लेकिन /etc/ssh/sshd_config जैसे defaults बदलते समय लोग और software changes को file या directive block के अंत में append करने की प्रवृत्ति रखते हैं, और उम्मीद करते हैं कि वह लागू होगा
    Security companies और organizations, कई SSH bastion products भी इसमें गलती करते हैं, और CIS Benchmarks की recommendations व ज्यादातर third-party CIS audit tools भी priority को consider नहीं करते या गलत handle करते हैं
    OpenSSH config directives उम्मीद के मुताबिक define हुए हैं या नहीं, यह check करने के लिए config file को खुद scan न करें; sshd -T या ssh -G से derived internal config dump करें

    • sudoers file भी इसी तरह काम करती है
      User authentication/authorization software में मुझे यह तरीका बेहतर लगता है
      क्योंकि whatever.conf.d directory में नई file जोड़कर भी ऐसी settings बनाना आसान है जिन्हें override नहीं किया जा सकता
      Main config file में whatever.conf.d/* include करने से पहले वह setting define कर दें, और उस file पर खास protection लगा दें
      कोई control bypass कर रहा हो ऐसा न भी हो, तब भी पूरे context को न जानने वाला junior नई file जोड़ दे या कोई package अपनी service के लिए अजीब default install कर दे, तो भी baseline setting को priority मिलती रहती है—इसलिए यह configuration management के लिए फायदेमंद है
      दूसरे contexts में उल्टा behavior ज्यादा दिखने की वजह यह है कि जो चाहिए वह “baseline setting” नहीं, बल्कि सख्त अर्थ में default value होती है, जो तब इस्तेमाल होती है जब user/developer/admin ने explicitly कुछ set नहीं किया हो
    • कुछ directives duplicate हो सकते हैं, ऐसा लगता है। उदाहरण के लिए AllowUsers
      हालांकि कल ही NixOS ने अचानक merge order बदल दिया, जिससे मेरी file का AllowUsers दूसरी file के Match के नीचे चला गया और lock हो गया
  • Article का सबसे important और concise sentence यह है कि -L में local forwarding के लिए local address के left में होता है, और -R में remote forwarding के लिए local port address के right में होता है—ऐसे याद रखें
    शुरू से ही -L और -R confuse करते रहे हैं, और port instance में कौन-सा local है यह L/R के हिसाब से बदलना काफी annoying है
    मैं समझता हूं कि -L और -R intended direction, यानी initiator और responder कहां हैं, यह बदलते हैं; लेकिन port:address:port को हमेशा local:binding:remote का मतलब रखने देना और -L/-R से यह तय कराना कि कौन-सी side receive करेगी और कौन-सी send, भी ठीक होता

    • याद रखने का सबसे आसान तरीका है: -L अपने तुरंत बाद आने वाले number के local port पर listen करता है, और -R अपने तुरंत बाद आने वाले number के remote port पर listen करता है
      बाकी host:port सिर्फ यह बताने का सामान्य format है कि connect कहां करना है
      चूंकि SSH tunnel के जरिए port forwarding की जा रही है, इसलिए यह भी स्वाभाविक रूप से follows करता है कि host को receiving port वाली side से tunnel के opposite side पर contact किया जाता है
  • SSH में कम चर्चित लेकिन उपयोगी फीचर के रूप में connection multiplexing है
    नया TCP connection बनाने और authentication प्रक्रिया फिर से करने के बजाय मौजूदा connection को reuse कराया जा सकता है
    protocol में ही channel की अवधारणा होती है, और हर data frame में अलग-अलग streams को पहचानने वाला metadata जुड़ा होता है; यह feature उसी का इस्तेमाल करता है
    बाद के sessions में पूरा authentication दोबारा न करना पड़े, यह बड़ा फायदा है
    remote पर tmux वगैरह न हो और आप कई terminal windows के जरिए कई panels इस्तेमाल करते हों, तो यह खास तौर पर अच्छा है; authentication में passphrase या HSM touch जैसी कुछ सेकंड लेने वाली प्रक्रिया हो तो फर्क और ज्यादा महसूस होता है
    “connection persistence” setting भी है, ताकि कुछ servers के बीच आते-जाते हर बार authenticate न करना पड़े
    कुल मिलाकर यह एक अच्छा-हो-तो-बढ़िया feature है, लेकिन जिंदगी बदल देने वाला नहीं
    कुछ servers पर यह feature बंद होता है; और इसकी कमी तब ज्यादा महसूस होती है जब यह off हो, compared to जब यह on हो
    और देखें: https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing

    • client और server के बीच latency ज्यादा हो तो फर्क बहुत बड़ा होता है
      SSH, TLS के उलट, जो round trips घटाने के लिए optimized है, काफी chatty protocol है; यह multiplexing option लगभग अकेला exception है
    • ProxyJump bastion host से गुजरते समय Ansible को इस्तेमाल करने में कहीं ज्यादा सुविधाजनक बना सकता है
  • अगर ~/.ssh/config में बहुत सारे hosts हैं, तो wildcard support करने वाले Include directive से file को बहुत messy होने से बचाया जा सकता है
    उदाहरण के लिए ~/.ssh/config में Include config.d/*.conf रखें, और ~/.ssh/config.d/work.conf या client1.conf में host, hostname, user settings अलग-अलग रख सकते हैं

    • Host directive भी wildcard support करता है
      उदाहरण के लिए host *_work जोड़कर host1_work जैसे सभी work hosts के लिए common settings डाल सकते हैं
    • एक और tip: Include को Host/Match directive के अंदर रखा जा सकता है
      उदाहरण के लिए ~/.ssh/config में Host proj1.*.corp और Include ~/.ssh/proj1.conf रखें, तो project-specific matches ऊपर के पास रखे जा सकते हैं और review करते समय ढेरों अलग-अलग files खंगालने की जरूरत भी कम होती है
  • forwarding करते समय मैं लगभग कभी -f इस्तेमाल नहीं करता
    इससे यह समझना मुश्किल हो सकता है कि कौन-सी forwarding अभी भी खुली और चल रही है, और यह अपने ही पैर पर कुल्हाड़ी जैसा बन सकता है
    -t एक बढ़िया trick है, और यह ऐसा feature था जिसके बारे में मुझे पता नहीं था
    ~ escape commands की list में आसानी से छूट जाने वाली अहम बात यह है कि nested sessions के अंदर भी escapes को nest किया जा सकता है
    किसी भी वजह से -J न इस्तेमाल कर रहे हों, तो यह उपयोगी है
    list उपयोगी चीजों से अच्छी तरह मेल खाती है, और कुछ नई बातें भी सीखने को मिलीं

    • -t शानदार है। मैं इसे ssh -t my-dev-vps 'tmux new-session -A -s main' की तरह इस्तेमाल करता हूं, ताकि हर बार चलाने पर सीधे tmux session की पिछली जगह पर लौट जाऊं
    • target server पर कई shells खुले हों, तब भी वही समस्या रहती है
      process list को खुद खंगालने के अलावा, अच्छा होगा अगर SSH किसी reasonable तरीके से forwarding status expose करे
  • AF_UNIX support जोड़ने वाला एक मौजूदा pull request है; अगर यह merge हो गया तो तरह-तरह की दिलचस्प forwarding संभव हो जाएगी
    वजह यह है कि किसी भी local process के जरिए SSH connection को proxy करना आसान हो जाएगा, और वह process remote end तक data पहुंचाने का काम अपनी तरह से handle कर सकेगा
    https://github.com/openssh/openssh-portable/pull/431

    • मेरी दिलचस्पी AF_UNIX इस्तेमाल करने वाले -D में है, लेकिन सब कुछ AF_UNIX के ऊपर चल सकना अच्छी बात है
      करीब 1 साल पहले से curl शायद ALL_PROXY syntax socks5://localhost/path या socks5h के जरिए AF_UNIX SOCKS इस्तेमाल कर सकता है
      लगता है यह इसलिए जोड़ा गया क्योंकि Tor AF_UNIX SOCKS proxy इस्तेमाल करता है
      standard Unix permissions से network access configure कर पाना अच्छा होगा, और निजी तौर पर तो TCP/IP को kernel से पूरी तरह बाहर धकेल पाना और भी बेहतर लगेगा
  • SSH console पहली बार देखकर मैं हैरान रह गया था
    एक colleague ने ~# दिखाया था, और ऐसा लगा जैसे SEGA Genesis game में मिलने वाला secret cheat menu खोज लिया हो

  • tilde क्यों? क्योंकि rlogin, rsh ने इसका इस्तेमाल किया था
    rlogin, rsh ने tilde क्यों इस्तेमाल किया? क्योंकि cu ने किया था
    cu क्यों? modem या serial line होने पर cu से communication करते थे, और Hayes codes भेजने होते थे; लेकिन Hayes code की escape sequence इस्तेमाल करने पर आप modem में निकल जाते, इसलिए cu से बाहर निकलने के लिए अलग signal चाहिए था
    ^[ क्यों नहीं? क्योंकि वह telnet का है
    इसलिए अगर आपने telnet से host में connect किया और फिर cu से modem में connect हुए, तो telnet से बाहर निकले बिना cu पर लौटने के लिए अलग escape syntax चाहिए था
    आखिरकार यह escape syntax की अंतहीन परतों वाला ढांचा है
    और असल में यह tilde नहीं, बल्कि tilde ही है

    • मैंने सोचा था क्रम CR, tilde, . होता है; क्या मैं अब तक गलत इस्तेमाल कर रहा था?
  • ssh-copy-id section पहले बताता है कि command public key upload करती है, फिर अचानक private key upload करने की बात पर बदल जाता है; यह typo लगता है
    साथ ही यह command सिर्फ key upload नहीं करती, बल्कि ~/.ssh/authorized_keys में append करती है, इसलिए यह कहीं ज्यादा उपयोगी है
    अंत में, ssh-keygen section में आजकल मैंने जो पढ़ा है उसके अनुसार ecdsa की तुलना में ed25519 को ज्यादा पसंद किया जाता है