[{"data":1,"prerenderedAt":804},["ShallowReactive",2],{"content:\u002Fposts\u002Fpowershell-ssh-config":3,"surround:\u002Fposts\u002Fpowershell-ssh-config":795},{"id":4,"title":5,"body":6,"categories":768,"date":770,"description":771,"draft":772,"extension":773,"image":774,"meta":775,"navigation":777,"path":778,"permalink":779,"pinned":772,"published":779,"readingTime":780,"recommend":779,"references":779,"seo":785,"sitemap":786,"stem":787,"tags":788,"type":792,"updated":793,"__hash__":794},"content\u002Fposts\u002Fposts\u002Fpowershell-ssh-config.md","PowerShell SSH 效率手册：免密、别名与端口转发",{"type":7,"value":8,"toc":746},"minimark",[9,19,22,25,30,33,44],[10,11,15],"alert",{"title":12,"type":13,"icon":14},"AI 迁移提示","info","tabler:robot",[16,17,18],"p",{},"本文由 AI 协助从旧站迁移，尚未完成逐篇人工审校；内容如有疏漏，将在复核后修订。",[10,20],{"title":21,"type":13},"> 本文部分内容由 AI 辅助整理，已结合实际操作进行校验，请根据自身环境谨慎使用。",[16,23,24],{},"Windows 10+ 自带的 OpenSSH 客户端已经很完善，配合 PowerShell Profile 和 SSH Config，运维里最常用的连服务器、免密、端口转发都能用一套干净的方式管理。本文记录我自己用得最顺手的一套配置。",[26,27,29],"h2",{"id":28},"_1-本地生成密钥只需执行一次","1. 本地生成密钥（只需执行一次）",[16,31,32],{},"在本地 PowerShell 运行：",[34,35,41],"pre",{"className":36,"code":38,"language":39,"meta":40},[37],"language-powershell","# 确保 .ssh 目录存在（全新账户第一次使用 SSH 时必要）\nif (!(Test-Path $HOME\\.ssh)) { New-Item -ItemType Directory $HOME\\.ssh | Out-Null }\n\n# 生成 ed25519 密钥，-N '' 表示不设密码\nssh-keygen -t ed25519 -N '' -f \"$HOME\\.ssh\\id_ed25519\"\n\n# 查看公钥内容\nGet-Content $HOME\\.ssh\\id_ed25519.pub\n","powershell","",[42,43,38],"code",{"__ignoreMap":40},[10,45,48,51,57,75,81,85,92,97,103,110,114,121,127,134,138,141,149,203,207,210,284,288,303,309,316,319,337,341,348,354,361,383,387,390,396,407,411,418,422,428,433,464,482,486,495,499,528,532,599,605,609,728,731,737,740,743],{"title":46,"type":47},"为什么选 ed25519","tip",[16,49,50],{},"ed25519 是目前推荐的密钥算法：公钥一行搞定、生成速度快、安全性更高。RSA 只在需要兼容十多年前的老系统时才需要考虑。",[16,52,53],{},[54,55,56],"strong",{},"要不要给密钥加 passphrase？",[16,58,59,60,63,64,67,68,70,71,74],{},"上面用 ",[42,61,62],{"code":62},"-N ''"," 生成的是",[54,65,66],{},"无密码私钥","，方便但一旦文件泄露就直接失守。对安全要求更高可以去掉 ",[42,69,62],{"code":62},"、交互式输入一个 passphrase。然后用 ",[42,72,73],{"code":73},"ssh-agent"," 托管密钥，每次登录不用反复输 passphrase：",[34,76,79],{"className":77,"code":78,"language":39,"meta":40},[37],"# 启用 ssh-agent 服务并设为开机自启（PowerShell 以管理员身份运行一次）\nStart-Service ssh-agent\nSet-Service ssh-agent -StartupType Automatic\n\n# 把密钥加入 agent（只需执行一次，之后重启电脑也会自动加载）\nssh-add $HOME\\.ssh\\id_ed25519\n",[42,80,78],{"__ignoreMap":40},[26,82,84],{"id":83},"_2-服务器端免密配置","2. 服务器端免密配置",[16,86,87,88,91],{},"把公钥送上服务器有三种方式，",[54,89,90],{},"推荐方式 A","（一行命令，不依赖额外工具）。",[93,94,96],"h3",{"id":95},"_21-方式-apipe-到-ssh-自动写入推荐","2.1 方式 A：pipe 到 ssh 自动写入（推荐）",[34,98,101],{"className":99,"code":100,"language":39,"meta":40},[37],"Get-Content $HOME\\.ssh\\id_ed25519.pub | ssh user@1.2.3.4 \"mkdir -p ~\u002F.ssh && chmod 700 ~\u002F.ssh && cat >> ~\u002F.ssh\u002Fauthorized_keys && chmod 600 ~\u002F.ssh\u002Fauthorized_keys\"\n",[42,102,100],{"__ignoreMap":40},[16,104,105,106,109],{},"命令会：读取本地公钥 → SSH 送到服务器 → 自动追加到 ",[42,107,108],{"code":108},"authorized_keys"," → 顺手把目录和文件权限都设对。执行时输一次密码，完成后下次起就免密。",[93,111,113],{"id":112},"_22-方式-bssh-copy-idopenssh-新版本自带","2.2 方式 B：ssh-copy-id（OpenSSH 新版本自带）",[16,115,116,117,120],{},"较新的 OpenSSH 客户端内置了 ",[42,118,119],{"code":119},"ssh-copy-id","，效果和方式 A 一致但命令更短：",[34,122,125],{"className":123,"code":124,"language":39,"meta":40},[37],"ssh-copy-id user@1.2.3.4\n",[42,126,124],{"__ignoreMap":40},[16,128,129,130,133],{},"Windows 自带的 OpenSSH 不一定带这个命令（看版本），如果提示 ",[42,131,132],{"code":132},"The term 'ssh-copy-id' is not recognized","，直接用方式 A。",[93,135,137],{"id":136},"_23-方式-c手动粘贴兜底","2.3 方式 C：手动粘贴（兜底）",[16,139,140],{},"登录服务器后手动执行（需要先把公钥内容复制到剪贴板）：",[34,142,147],{"className":143,"code":145,"language":146,"meta":40},[144],"language-bash","mkdir -p ~\u002F.ssh && chmod 700 ~\u002F.ssh && \\\necho \"这里粘贴公钥内容\" >> ~\u002F.ssh\u002Fauthorized_keys && \\\nchmod 600 ~\u002F.ssh\u002Fauthorized_keys\n","bash",[42,148,145],{"__ignoreMap":40},[150,151,152,153,160,168,183,189],"caution",{},"免密配好后建议禁用密码登录",[16,154,155,156,159],{},"公钥登录正常工作后，推荐在服务器 ",[42,157,158],{"code":158},"\u002Fetc\u002Fssh\u002Fsshd_config"," 里改成：",[34,161,166],{"className":162,"code":164,"language":165},[163],"language-text","PubkeyAuthentication yes\nPasswordAuthentication no\n","text",[42,167,164],{"__ignoreMap":40},[16,169,170,171,174,175,178,179,182],{},"然后 ",[42,172,173],{"code":173},"sudo systemctl reload ssh","（Debian\u002FUbuntu 是 ",[42,176,177],{"code":177},"ssh","，CentOS\u002FRHEL 是 ",[42,180,181],{"code":181},"sshd","）。这样服务器只接受密钥登录，彻底消除密码被爆破的风险。",[16,184,185,188],{},[54,186,187],{},"两条关键保险","：",[190,191,192,196],"ol",{},[193,194,195],"li",{},"修改前务必先用密钥登录一次，确认公钥配置无误。",[193,197,198,199,202],{},"修改和 reload 期间",[54,200,201],{},"保留一个已登录的 SSH 窗口别关","——万一配置语法错、reload 失败或被防火墙误杀，可以从这个窗口里回滚，而不是被锁在门外。",[26,204,206],{"id":205},"_3-ssh-端口转发的三种模式","3. SSH 端口转发的三种模式",[16,208,209],{},"SSH 内置 3 种端口转发模式，分别应对不同场景：",[211,212,213,232],"table",{},[214,215,216],"thead",{},[217,218,219,223,226,229],"tr",{},[220,221,222],"th",{},"模式",[220,224,225],{},"参数",[220,227,228],{},"方向",[220,230,231],{},"典型场景",[233,234,235,252,268],"tbody",{},[217,236,237,241,246,249],{},[238,239,240],"td",{},"本地转发",[238,242,243],{},[42,244,245],{"code":245},"-L",[238,247,248],{},"本地 → 远程",[238,250,251],{},"访问远程内网 Web \u002F DB",[217,253,254,257,262,265],{},[238,255,256],{},"远程转发",[238,258,259],{},[42,260,261],{"code":261},"-R",[238,263,264],{},"远程 → 本地",[238,266,267],{},"把本地服务暴露给远端（内网穿透）",[217,269,270,273,278,281],{},[238,271,272],{},"动态转发",[238,274,275],{},[42,276,277],{"code":277},"-D",[238,279,280],{},"SOCKS 代理",[238,282,283],{},"浏览器流量整条走 SSH",[93,285,287],{"id":286},"_31-本地转发-l最常用","3.1 本地转发（-L）——最常用",[16,289,290,291,294,295,298,299,302],{},"把",[54,292,293],{},"远端能访问的资源","映射到",[54,296,297],{},"本地端口","。比如服务器上跑着只监听 ",[42,300,301],{"code":301},"127.0.0.1:8080"," 的内部 Web 面板：",[34,304,307],{"className":305,"code":306,"language":39,"meta":40},[37],"# 格式：ssh -L [本地端口]:[远端可访问地址]:[远端端口] 用户@服务器IP\n# 示例：把服务器的 127.0.0.1:8080 映射到本地 8080\nssh -L 8080:127.0.0.1:8080 user@1.2.3.4\n",[42,308,306],{"__ignoreMap":40},[16,310,311,312,315],{},"连上后，本地浏览器访问 ",[42,313,314],{"code":314},"http:\u002F\u002Flocalhost:8080"," 就是在访问服务器上的服务。",[16,317,318],{},"常用参数：",[320,321,322,328],"ul",{},[193,323,324,327],{},[42,325,326],{"code":326},"-N","：只建隧道，不打开远程 shell",[193,329,330,333,334,336],{},[42,331,332],{"code":332},"-f","：执行命令前 fork 到后台（通常和 ",[42,335,326],{"code":326}," 一起用，让 SSH 进程进入后台运行）",[93,338,340],{"id":339},"_32-远程转发-r内网穿透","3.2 远程转发（-R）——内网穿透",[16,342,343,344,347],{},"方向相反：把",[54,345,346],{},"本地能访问的服务","暴露给远端。比如想让服务器访问你本地 3000 端口的服务：",[34,349,352],{"className":350,"code":351,"language":39,"meta":40},[37],"# 把本地 localhost:3000 映射到服务器的 8000 端口\nssh -R 8000:localhost:3000 user@1.2.3.4\n",[42,353,351],{"__ignoreMap":40},[16,355,356,357,360],{},"服务器上访问 ",[42,358,359],{"code":359},"http:\u002F\u002F127.0.0.1:8000"," 就是访问你本地的 3000，常用于给服务器演示本地 demo、接收 webhook 调试等。",[16,362,363,367,368,370,371,374,375,378,379,382],{},[364,365,366],"span",{},"!WARNING"," -R 默认只监听 127.0.0.1\n服务器上 ",[42,369,261],{"code":261}," 暴露出来的端口默认只绑定 ",[42,372,373],{"code":373},"127.0.0.1","，外部机器访问不到。如果要让公网或局域网也能访问，需要在服务器 ",[42,376,377],{"code":377},"sshd_config"," 里开启 ",[42,380,381],{"code":381},"GatewayPorts yes","——安全敏感，谨慎使用。",[93,384,386],{"id":385},"_33-动态转发-dsocks-代理","3.3 动态转发（-D）——SOCKS 代理",[16,388,389],{},"把 SSH 当成本地 SOCKS5 代理：",[34,391,394],{"className":392,"code":393,"language":39,"meta":40},[37],"# 在本地 1080 端口起 SOCKS5 代理，所有流量走服务器\nssh -D 1080 -N user@1.2.3.4\n",[42,395,393],{"__ignoreMap":40},[16,397,398,399,402,403,406],{},"浏览器把代理设成 SOCKS5 ",[42,400,401],{"code":401},"127.0.0.1:1080"," 后，所有网页请求都会经服务器出口。相当于",[54,404,405],{},"一条 SSH 连接就能当整套代理","，临时用不需要单独装 Clash \u002F v2ray 这类工具。",[26,408,410],{"id":409},"_4-短别名与自动端口转发两种方案","4. 短别名与自动端口转发：两种方案",[16,412,413,414,417],{},"每次敲 ",[42,415,416],{"code":416},"ssh -L ... user@ip"," 又长又容易出错。下面两种方案都能做到\"一个词解决\"，按需选一种或两种搭配用。",[93,419,421],{"id":420},"_41-方案一ssh-config-文件推荐","4.1 方案一：SSH Config 文件（推荐）",[16,423,424,427],{},[54,425,426],{},"优点","：声明式配置；命令行、Git、SCP 等各种 SSH 工具都认；一次配置终身受益。",[16,429,430,188],{},[54,431,432],{},"步骤",[190,434,435,444,455],{},[193,436,437,438],{},"打开配置文件：",[34,439,442],{"className":440,"code":441,"language":39,"meta":40},[37],"notepad $HOME\\.ssh\\config\n",[42,443,441],{"__ignoreMap":40},[193,445,446,447],{},"写入内容：",[34,448,453],{"className":449,"code":451,"language":452,"meta":40},[450],"language-ssh-config","# --- 基础服务器：只做登录 ---\nHost s1\n    HostName 1.2.3.4\n    User user\n    Port 22                # 非默认端口（如 22222）就改这里\n    IdentityFile ~\u002F.ssh\u002Fid_ed25519\n\n# --- 带自动端口转发的同一台服务器 ---\nHost s1-tunnel\n    HostName 1.2.3.4\n    User user\n    Port 22\n    IdentityFile ~\u002F.ssh\u002Fid_ed25519\n    # LocalForward [本地端口] [目标地址]:[目标端口]\n    LocalForward 18789 127.0.0.1:18789\n    LocalForward 3306 127.0.0.1:3306\n","ssh-config",[42,454,451],{"__ignoreMap":40},[193,456,457,458],{},"使用：",[34,459,462],{"className":460,"code":461,"language":39,"meta":40},[37],"ssh s1              # 纯登录\nssh s1-tunnel       # 登录 + 自动把 18789 \u002F 3306 映射到本地\n",[42,463,461],{"__ignoreMap":40},[16,465,466,469,470,473,474,477,478,481],{},[364,467,468],{},"!TIP"," 用 IdentityFile 管理多密钥\n如果不同服务器需要不同密钥（比如公司机和 HomeLab 分开），在每个 ",[42,471,472],{"code":472},"Host"," 块下单独写 ",[42,475,476],{"code":476},"IdentityFile","，SSH 会按主机挑对应密钥，不会把所有私钥依次试一遍（那样很快就会撞到服务器端 ",[42,479,480],{"code":480},"MaxAuthTries"," 限制被拒绝）。",[93,483,485],{"id":484},"_42-方案二powershell-profile-函数","4.2 方案二：PowerShell Profile 函数",[16,487,488,490,491,494],{},[54,489,426],{},"：启动时可以打印友好提示、函数里能塞任意 PowerShell 逻辑（例如连前先 ",[42,492,493],{"code":493},"Test-NetConnection"," 探活）。",[16,496,497,188],{},[54,498,432],{},[190,500,501,510,519],{},[193,502,503,504],{},"打开 Profile：",[34,505,508],{"className":506,"code":507,"language":39,"meta":40},[37],"notepad $PROFILE\n",[42,509,507],{"__ignoreMap":40},[193,511,512,513],{},"写入函数：",[34,514,517],{"className":515,"code":516,"language":39,"meta":40},[37],"# 1. 纯连接\nfunction s1 { ssh user@1.2.3.4 }\n\n# 2. 一键开启端口转发并显示提示\nfunction s1-tunnel {\n    Write-Host \"------------------------------------------------\" -ForegroundColor Cyan\n    Write-Host \"SSH 隧道已建立！\" -ForegroundColor Green\n    Write-Host \"Web 应用: http:\u002F\u002Flocalhost:18789\" -ForegroundColor Yellow\n    Write-Host \"数据库端口: 3306 -> 3306\" -ForegroundColor Yellow\n    Write-Host \"提示: 保持此窗口开启，按 Ctrl+C 关闭隧道\" -ForegroundColor DarkGray\n    Write-Host \"------------------------------------------------\" -ForegroundColor Cyan\n    # -N 表示不执行远程命令，仅做转发\n    ssh -N -L 18789:127.0.0.1:18789 -L 3306:127.0.0.1:3306 user@1.2.3.4\n}\n",[42,518,516],{"__ignoreMap":40},[193,520,521,522],{},"让配置生效并使用：",[34,523,526],{"className":524,"code":525,"language":39,"meta":40},[37],". $PROFILE       # 立即加载本次会话\ns1-tunnel        # 直接输入函数名\n",[42,527,525],{"__ignoreMap":40},[93,529,531],{"id":530},"_43-两种方案对比","4.3 两种方案对比",[211,533,534,547],{},[214,535,536],{},[217,537,538,541,544],{},[220,539,540],{},"维度",[220,542,543],{},"Config 方式",[220,545,546],{},"Profile 方式",[233,548,549,566,577,588],{},[217,550,551,554,560],{},[238,552,553],{},"打字量",[238,555,556,559],{},[42,557,558],{"code":558},"ssh s1-tunnel","（中等）",[238,561,562,565],{},[42,563,564],{"code":564},"s1-tunnel","（最少）",[217,567,568,571,574],{},[238,569,570],{},"可维护性",[238,572,573],{},"高（标准格式、跨工具通用）",[238,575,576],{},"一般（仅 PowerShell 生效）",[217,578,579,582,585],{},[238,580,581],{},"自动化能力",[238,583,584],{},"声明式配端口，无逻辑",[238,586,587],{},"可写任意 PowerShell 脚本逻辑",[217,589,590,593,596],{},[238,591,592],{},"推荐度",[238,594,595],{},"⭐⭐⭐⭐⭐",[238,597,598],{},"⭐⭐⭐（补充）",[16,600,601,604],{},[54,602,603],{},"建议方案一为主、方案二为辅","：能用 Config 解决的就用 Config，需要彩色提示 \u002F 脚本逻辑时再走 Profile 函数。",[26,606,608],{"id":607},"_5-常见故障排查","5. 常见故障排查",[211,610,611,624],{},[214,612,613],{},[217,614,615,618,621],{},[220,616,617],{},"报错",[220,619,620],{},"原因",[220,622,623],{},"对策",[233,625,626,643,666,684,706],{},[217,627,628,633,636],{},[238,629,630],{},[42,631,632],{"code":632},"Permissions 0644 for 'id_ed25519' are too open",[238,634,635],{},"本地私钥权限过松",[238,637,638,639,642],{},"PowerShell 运行 ",[42,640,641],{"code":641},"icacls $HOME\\.ssh\\id_ed25519 \u002Finheritance:r \u002Fgrant:r \"$($env:USERNAME):F\"","，或手动在文件属性里只保留当前用户可读",[217,644,645,651,660],{},[238,646,647,648],{},"服务器侧 ",[42,649,650],{"code":650},"Permission denied (publickey)",[238,652,653,656,657,659],{},[42,654,655],{"code":655},"~\u002F.ssh"," 或 ",[42,658,108],{"code":108}," 权限不对",[238,661,662,663],{},"服务器上执行 ",[42,664,665],{"code":665},"chmod 700 ~\u002F.ssh && chmod 600 ~\u002F.ssh\u002Fauthorized_keys",[217,667,668,674,677],{},[238,669,670,671],{},"端口转发报 ",[42,672,673],{"code":673},"bind: Address already in use",[238,675,676],{},"本地端口被其他进程占用",[238,678,679,680,683],{},"PowerShell 里 ",[42,681,682],{"code":682},"Get-NetTCPConnection -LocalPort 8080"," 定位占用进程",[217,685,686,689,696],{},[238,687,688],{},"能连上但卡很久才出提示符",[238,690,691,692,695],{},"服务器开了 ",[42,693,694],{"code":694},"UseDNS"," 但反向解析失败",[238,697,698,699,701,702,705],{},"服务器 ",[42,700,377],{"code":377}," 里设 ",[42,703,704],{"code":704},"UseDNS no"," 后重启 sshd",[217,707,708,711,714],{},[238,709,710],{},"没明显报错但连不上 \u002F 认证反复失败",[238,712,713],{},"需要更详细调试信息",[238,715,716,717,720,721,720,724,727],{},"加 ",[42,718,719],{"code":719},"-v"," \u002F ",[42,722,723],{"code":723},"-vv",[42,725,726],{"code":726},"-vvv"," 打印握手日志（见下方）",[16,729,730],{},"遇到复杂问题时的万能调试命令：",[34,732,735],{"className":733,"code":734,"language":39,"meta":40},[37],"ssh -vvv s1-tunnel\n",[42,736,734],{"__ignoreMap":40},[16,738,739],{},"输出会逐步打印 SSH 协议握手的每个阶段，对密钥不匹配、配置未生效、算法协商失败等问题定位非常有用。",[741,742],"hr",{},[16,744,745],{},"本教程在 Windows 11 + OpenSSH 9.x 客户端上验证过。对端服务器可以是 Linux \u002F macOS，SSH 协议两端一致，命令互通。",{"title":40,"searchDepth":747,"depth":747,"links":748},4,[749,751,757,762,767],{"id":28,"depth":750,"text":29},2,{"id":83,"depth":750,"text":84,"children":752},[753,755,756],{"id":95,"depth":754,"text":96},3,{"id":112,"depth":754,"text":113},{"id":136,"depth":754,"text":137},{"id":205,"depth":750,"text":206,"children":758},[759,760,761],{"id":286,"depth":754,"text":287},{"id":339,"depth":754,"text":340},{"id":385,"depth":754,"text":386},{"id":409,"depth":750,"text":410,"children":763},[764,765,766],{"id":420,"depth":754,"text":421},{"id":484,"depth":754,"text":485},{"id":530,"depth":754,"text":531},{"id":607,"depth":750,"text":608},[769],"Linux","2026-03-07","在 Windows PowerShell 下用 OpenSSH 实现 ed25519 免密登录、SSH Config 短别名、本地\u002F远程\u002F动态三种端口转发以及多密钥管理。",false,"md","https:\u002F\u002Fimg.olinl.com\u002Ffile\u002Fpost-img\u002Fcover\u002Fdb5kEm31.webp",{"slots":776},{},true,"\u002Fposts\u002Fpowershell-ssh-config",null,{"text":781,"minutes":782,"time":783,"words":784},"11 min read",10.275,616500,2055,{"title":5,"description":771},{"loc":778},"posts\u002Fposts\u002Fpowershell-ssh-config",[789,790,791],"PowerShell","SSH","OpenSSH","tech","2026-07-26 13:31:43","0KOl-1VKRUprspVK3SGyXzo6038LkfigHIpJegXLjxw",[796,799],{"title":5,"path":797,"stem":798,"date":770,"type":792,"children":-1},"\u002Fposts\u002Fpowershell-ssh-config-guide","posts\u002Fposts\u002Fpowershell-ssh-config-guide",{"title":800,"path":801,"stem":802,"date":803,"type":792,"children":-1},"将“上游项目”的更新合并到“我的项目”上","\u002Fposts\u002Fmerge-upstream-branches","posts\u002Fposts\u002Fmerge-upstream-branches","2026-03-08",1788712223431]