编程语言语言运行时标准库编译器并发编程【免费下载链接】otpErlang/OTP项目地址https://gitcode.com/gh_mirrors/ot/otp点击查看免费下载导读OTP 的 SSH 应用sshapplication提供了数量庞大的可配置选项Options覆盖客户端连接、服务端守护进程、算法协商、认证与密钥管理等多个层面。本文以 lib/ssh/doc/guides/configurations.md 为核心系统讲解这些选项的所有设置入口、四层优先级规则以及preferred_algorithms与modify_algorithms在不同层级间的协作机制。读完本文你将掌握在 Erlang 代码、erl 命令行、ssh.app与.config文件中分别配置 SSH 选项的正确姿势理解谁覆盖谁的优先级语义并能通过配置文件为遗留系统安全地启用已被默认集移除的算法。一、设置 Option 的两条主要途径OTP SSH 应用支持通过两种途径设置选项且二者可以混用Erlang 代码中的Options参数在调用ssh:daemon/3、ssh:connect/3及其变体时直接传入选项列表OTP 配置参数Configuration Parameters通过erl命令行、应用配置文件等 OTP 标准机制注入参见 OTP 配置参数说明。1.1 在函数调用中直接传入最直观的方式是把选项作为参数列表传给相关函数ssh:connect(22, [{user,foo}]).这里user被设置为foo客户端将以该用户名发起连接。同样的机制适用于ssh:connect/2,3,4、ssh:daemon/1,2,3等所有接受选项列表的公开 API。1.2 通过 OTP 配置参数注入配置参数有三种写入位置均会在应用启动时被读取。1erl 命令行erl -ssh user foo-ssh之后的key value对会被 OTP 写入ssh应用的环境变量application environment等效于设置application:set_env(ssh, user, foo)。2ssh.app文件的env部分在应用的.app资源文件的env元组中列出默认环境变量。以源码仓库中的 lib/ssh/src/ssh.app.src 为模板构建时%VSN%会被替换为实际版本号示例如下{application, ssh, [{description, SSH-2 for Erlang/OTP}, {vsn, 4.9}, {modules, [ssh, ... ssh_xfer]}, {registered, []}, {applications, [kernel, stdlib, crypto, public_key]}, {env, [{user, bar}]}, % HERE {mod, {ssh_app, []}}, ...注意applications列表声明了 ssh 对kernel、stdlib、crypto、public_key的依赖——其中crypto与public_key正是算法协商与密钥处理的基础。3.config文件把配置写入独立的 config 文件再通过erl -config加载erl -config ex1其中ex1.config内容为[{ssh, [{user, foo}]}].顶层元组的第一项ssh指明这是ssh应用的配置其值为一个选项属性列表。1.3 按角色隔离server_options 与 client_options如果某选项只针对服务端或只针对客户端可以把它放入server_options或client_options从而让同一份配置同时为两侧提供不同取值[{ssh, [{server_options, [{user, foo}]}, {client_options, [{user, bar}]}]}].此时**守护进程daemon使用用户名foo而客户端client**使用用户名bar。从源码看这一角色映射实现在 lib/ssh/src/ssh_options.erl 的cnf_key/1cnf_key(server) - server_options; cnf_key(client) - client_options.即服务端只从server_options读取角色化配置客户端只读取client_options。二、优先级四级覆盖规则当同一个选项通过多种方式被设置时遵循严格的优先级顺序。从低到高依次为级别来源说明Level 0OTP SSH 源码中的硬编码默认值由 lib/ssh/src/ssh_options.erl 的default/1及 lib/ssh/src/ssh_transport.erl 的default_algorithms1/1等定义Level 1OTP 配置参数即erl -ssh ...命令行、ssh.app的env、.config文件直接列出的选项Level 2配置参数中的server_options/client_options角色化包装的选项Level 3函数调用参数列表ssh:connect/3、ssh:daemon/3等调用中直接传入的选项同一选项若在多个层级被设置取最高层级的值。因此函数调用参数Level 3始终覆盖配置文件Level 1/2而配置文件又覆盖源码硬编码默认值Level 0。唯一的例外modify_algorithmsmodify_algorithms是一个累积型选项而非取高者选项。所有层级上的modify_algorithms会按层级从低到高的顺序依次应用到算法集合上Level 1 的修改先执行随后是 Level 2最后是 Level 3。如果某个层级出现了preferred_algorithms则该层的整个算法集会被替换为该选项指定的集合然后所有层级的modify_algorithms依旧按层级顺序施加在该结果之上。之所以这样设计是为了让用户无需修改任何代码仅通过在配置文件中添加一个选项就能把已被默认集移除的算法重新加回来以便与仍在使用旧算法的遗留系统互通。例如可以通过配置文件把ssh-dss这类已从默认集删除的公钥算法重新启用详见下文跨层级 modify_algorithms 示例。三、算法配置层级如何作用于算法集preferred_algorithms与modify_algorithms的协作细节有专门的章节说明参见 Configuring algorithms in SSH本节聚焦不同配置层级对它们的影响。3.1 ssh:start/0 前后的 default_algorithms 差异ssh:default_algorithms/0的返回值取决于 ssh 应用是否已启动应用未启动时返回硬编码默认算法列表Level 0但已经根据当前 cryptolibcrypto应用实际支持的能力做了裁剪应用已启动ssh:start/0后返回应用了 Level 0 与 Level 1 配置之后的算法列表。用文档中的完整示例验证。配置文件ex2.config$ cat ex2.config [{ssh, [{preferred_algorithms, [{cipher, [aes192-ctr]}, {public_key, [ssh-rsa]}, {kex, [ecdh-sha2-nistp384]}, {mac, [hmac-sha1]}]}]}].启动 Erlang 并加载该配置先不启动 ssh$ erl -config ex2 Erlang/OTP 29 [erts-16.3.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns] Eshell V16.3.1 (press CtrlG to abort, type help(). for help) 1 ssh:default_algorithms(). [{kex,[mlkem768x25519-sha256,curve25519-sha256, curve25519-sha256libssh.org,curve448-sha512, ecdh-sha2-nistp521,ecdh-sha2-nistp384, ecdh-sha2-nistp256, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256]}, {public_key,[ssh-ed25519,ssh-ed448,ecdsa-sha2-nistp521, ecdsa-sha2-nistp384,ecdsa-sha2-nistp256, rsa-sha2-512,rsa-sha2-256]}, {cipher,[{client2server,[aes256-gcmopenssh.com,aes256-ctr, aes192-ctr,aes128-gcmopenssh.com, aes128-ctr, chacha20-poly1305openssh.com]}, {server2client,[aes256-gcmopenssh.com,aes256-ctr, aes192-ctr,aes128-gcmopenssh.com, aes128-ctr, chacha20-poly1305openssh.com]}]}, {mac,[{client2server,[hmac-sha2-512-etmopenssh.com, hmac-sha2-256-etmopenssh.com, hmac-sha2-512,hmac-sha2-256, hmac-sha1-etmopenssh.com,hmac-sha1]}, {server2client,[hmac-sha2-512-etmopenssh.com, hmac-sha2-256-etmopenssh.com, hmac-sha2-512,hmac-sha2-256, hmac-sha1-etmopenssh.com,hmac-sha1]}]}, {compression,[{client2server,[none,zlibopenssh.com]}, {server2client,[none,zlibopenssh.com]}]}]注意此时ex2.config中的算法尚未生效——它们会在启动 ssh 时被应用2 ssh:start(). ok 3 ssh:default_algorithms(). [{kex,[ecdh-sha2-nistp384]}, {public_key,[ssh-rsa]}, {cipher,[{client2server,[aes192-ctr]}, {server2client,[aes192-ctr]}]}, {mac,[{client2server,[hmac-sha1]}, {server2client,[hmac-sha1]}]}, {compression,[{client2server,[none,zlibopenssh.com]}, {server2client,[none,zlibopenssh.com]}]}] 4可以看到算法集被替换成了ex2.config中指定的内容。由于配置中没有指定compression该项仍然保留硬编码默认值[none, zlibopenssh.com]——即 Level 1 只覆盖它显式列出的类别其余类别继续回落到 Level 0 默认值。从源码层面看这个启动前后差异是由 lib/ssh/src/ssh.erl 的start/1实现的start(Type) - case application:ensure_all_started(ssh, Type) of {ok, _} - %% Clear cached default_algorithms (if exists) ... ssh_transport:clear_default_algorithms_env(), %% ... and rebuild them taking configure options in account ssh_transport:default_algorithms(), ok; Other - Other end.启动成功后先清除缓存clear_default_algorithms_env/0再基于当前配置重建默认算法集。而 lib/ssh/src/ssh_transport.erl 中的default_algorithms/0带有缓存与 FIPS 模式感知逻辑default_algorithms() - FipsMode crypto:info_fips(), case application:get_env(ssh, ?DEFAULT_ALGS) of undefined - Algs build_cache(), application:set_env(ssh, ?DEFAULT_ALGS, {FipsMode,Algs}), Algs; {ok,{FipsMode,Algs}} - %% Cached, and the FIPS mode is the same now as when it was cached. Algs; {ok,{_OtherFipsMode,_Algs}} - %% Cached, but the FIPS mode has changed. Algs build_cache(), application:set_env(ssh, ?DEFAULT_ALGS, {FipsMode,Algs}), Algs end.算法结果缓存在内部应用环境键$def-algs$中且缓存与crypto:info_fips()的 FIPS 模式绑定——当 FIPS 模式发生变化时缓存会失效并重建。build_cache/0则负责真正合并配置build_cache() - Opts get_alg_conf(), Algs1 case proplists:get_value(preferred_algorithms, Opts) of undefined - [{K,default_algorithms1(K)} || K - algo_classes()]; Algs0 - {true,Algs01} ssh_options:check_preferred_algorithms(Algs0), Algs01 end, Algs case proplists:get_value(modify_algorithms, Opts) of undefined - Algs1; Modifications - ssh_options:initial_default_algorithms(Algs1, Modifications) end, Algs.其中get_alg_conf/0从应用环境读取preferred_algorithms与modify_algorithms对应 Level 1 配置default_algorithms1/1定义了每个算法类别的默认集合例如kex的默认集中明确排除了diffie-hellman-group1-sha1、diffie-hellman-group14-sha1、diffie-hellman-group-exchange-sha1分别在 OpenSSH 7.3.p1 与 8.2 中移除public_key的默认集排除了ssh-rsa与ssh-dss最终再经由supported_algorithms/1的select_crypto_supported/1按当前 cryptolib 的实际能力裁剪。算法类别algo_classes()固定为[kex, public_key, cipher, mac, compression]。3.2 ssh:connect 与 ssh:daemon 中的算法选项客户端通过ssh:connect/2,3,4等建立连接时、服务端通过ssh:daemon/1,2,3启动时函数调用参数列表中的选项同样参与算法协商客户端连接时使用环境变量client_optionsLevel 2 的客户端侧守护进程启动时使用server_optionsLevel 2 的服务端侧。当存在多个层级的preferred_algorithms时取最高层级的那一个——即函数调用参数列表Level 3优先级最高随后从 Level 0 开始按顺序应用所有层级的modify_algorithms。继续上面的例子。连接一台服务器通过modify_algorithms删除当前唯一的kex算法ecdh-sha2-nistp384并把curve25519-sha256libssh.org追加到删除后空列表中4 {ok,C} ssh:connect(loopback, 22, [{modify_algorithms, [{rm, [{kex, [ecdh-sha2-nistp384]}]}, {append, [{kex, [curve25519-sha256libssh.org]}]}]}]). {ok,0.118.0}通过ssh:connection_info/2检查客户端与服务端实际协商出的算法可以看到唯一的kex算法curve25519-sha256libssh.org被选中5 ssh:connection_info(C, algorithms). {algorithms,[{kex,curve25519-sha256libssh.org}, {hkey,ssh-rsa}, {send_mac,hmac-sha1}, {recv_mac,hmac-sha1}, {encrypt,aes192-ctr}, {decrypt,aes192-ctr}, {compress,none}, {decompress,none}, {send_ext_info,false}, {recv_ext_info,true}]}3.3 跨层级 modify_algorithms 示例用配置文件启用 ssh-dss下面验证一个关键机制低层级的modify_algorithms是否作用于高层级的preferred_algorithms。做法是通过配置文件启用虽然受支持、但不在默认集中的ssh-dss算法。配置文件ex3.config[{ssh, [{modify_algorithms, [{prepend, [{public_key, [ssh-dss]}]}]}]}].新建的 Erlang shell 中可以看到public_key项里并没有ssh-dss1 proplists:get_value(public_key, ssh:default_algorithms()). [ssh-ed25519,ssh-ed448,ecdsa-sha2-nistp521, ecdsa-sha2-nistp384,ecdsa-sha2-nistp256, rsa-sha2-512,rsa-sha2-256] 2随后调用ssh:connect/3在参数列表中用preferred_algorithms把每类算法削减到只剩一个2 ssh:start(). ok 3 {ok,C} ssh:connect(loopback, 22, [{preferred_algorithms, [{public_key, [ecdsa-sha2-nistp256]}, {kex, [ecdh-sha2-nistp256]}, {cipher, [chacha20-poly1305openssh.com]}, {mac, [hmac-sha2-256]}, {compression, [none]}]}]). {ok,0.101.0} 4 ssh:connection_info(C,algorithms). {algorithms,[{kex,ecdh-sha2-nistp256}, {hkey,ssh-dss}, {send_mac,chacha20-poly1305openssh.com}, {recv_mac,chacha20-poly1305openssh.com}, {encrypt,chacha20-poly1305openssh.com}, {decrypt,chacha20-poly1305openssh.com}, {compress,none}, {decompress,none}, {send_ext_info,false}, {recv_ext_info,true}]} 5调用虽然只允许了ecdsa-sha2-nistp256但最终选中的公钥算法却是ssh-dss——来自ex3.configLevel 1中modify_algorithms的prepend操作被应用到了函数调用Level 3的preferred_algorithms之上。完整公钥算法列表实际为[ssh-dss,ecdsa-sha2-nistp256]prepend把ssh-dss放在最前因此协商优先选择了ssh-dss。这个例子证明了仅靠修改配置文件就能在不改动任何调用代码的前提下扩充算法集。需要说明的是示例故意使用prepend而非append来强制协商选中ssh-dss实际生产环境中更稳妥的做法是用append把非默认算法追加到列表末尾从而保持默认算法的优先级。3.4 修改操作的底层语义从源码可以确认modify_algorithms三类操作的精确语义。在 lib/ssh/src/ssh_options.erl 中eval_op(rm, Opt, Pref, []) when is_list(Opt), is_list(Pref) - Pref -- Opt; eval_op(append, Opt, Pref, []) when is_list(Opt), is_list(Pref) - (Pref--Opt) Opt; eval_op(prepend, Opt, Pref, []) when is_list(Opt), is_list(Pref) - Opt (Pref--Opt).rm从偏好列表Pref中删除Opt列出的算法append先删除再追加即把Opt中的算法移到列表末尾避免重复prepend把Opt中的算法置于列表最前先删除原位置再置顶。所有modify_algorithms输入还会经过check_modify_algorithms/1校验只接受append、prepend、rm三种二元组操作且算法列表不允许重复、只允许原子再经rm_non_supported/2与 lib/ssh/src/ssh_transport.erl 的supported_algorithms/1比对剔除当前 cryptolib 不支持的算法。preferred_algorithms与modify_algorithms的最终合并发生在final_preferred_algorithms/1它把modify_algorithms施加到preferred_algorithms上——这正是上一节跨层级示例能够生效的代码级原因。四、配置选项的合并顺序与校验结合 lib/ssh/src/ssh_options.erl 的config_val/3可以看到每个选项的取值来源按如下顺序合并config_val(Key, RoleCnfs, Opts) - case lists:keysearch(Key, 1, Opts) of {value, {_,V}} - {ok,V}; false - case lists:keysearch(Key, 1, RoleCnfs) of {value, {_,V}} - {ok,V}; false - application:get_env(ssh, Key) % returns {ok,V} | undefined end end.即优先级函数调用参数Level 3 →server_options/client_optionsLevel 2 → 应用环境/配置文件Level 1最终落到default/1定义的硬编码默认值Level 0。而modify_algorithms走的是专门的config_val/3分支把三层来源**全部串接**起来构成按层级顺序全部应用的累积语义config_val(modify_algorithmsKey, RoleCnfs, Opts) - V case application:get_env(ssh, Key) of {ok,V0} - V0; _ - [] end proplists:get_value(Key, RoleCnfs, []) proplists:get_value(Key, Opts, []), case V of [] - undefined; _ - {append,V} end;每个选项在保存前还会经过OptionDefinitionsdefault/1返回的表中声明的chk校验函数例如preferred_algorithms对应check_preferred_algorithms/1、modify_algorithms对应check_modify_algorithms/1非法取值会抛出{error,{EO,KV,Reason}}形式的错误其中EO为eoptions选项列表错误或eerl_enverl 环境错误便于定位问题来源。五、相关阅读安全加固相关的选项配置参见 Hardening SSHpreferred_algorithms与modify_algorithms的协作细则及更多示例参见 Configuring algorithms in SSHOTP 配置参数机制的通用说明erl -config、应用环境等参见 OTP 配置参数全部选项的定义与校验逻辑位于 lib/ssh/src/ssh_options.erl算法默认集与 cryptolib 能力裁剪位于 lib/ssh/src/ssh_transport.erlssh:default_algorithms/0、ssh:connect/3、ssh:daemon/3等公开接口定义于 lib/ssh/src/ssh.erl应用资源文件模板为 lib/ssh/src/ssh.app.src。赞分享编程语言语言运行时标准库编译器并发编程【免费下载链接】otpErlang/OTP项目地址https://gitcode.com/gh_mirrors/ot/otp点击查看免费下载相关推荐Erlang/OTP SSH 算法配置完全指南从协商机制到 preferred_algorithms 与 modify_algorithms 实战Erlang/OTP SSH 算法配置完全指南从协商机制到 preferred_algorithms 与 modify_algorithms 实战 本文以 O编程语言语言运行时标准库编译器并发编程**Erlang/OTP 安装与配置完全指南**Erlang/OTP 安装与配置完全指南 项目基础介绍及主要编程语言 Erlang/OTP 是一个专为构建高度可扩展的软实时系统设计的编程语言及其运行时环境。它编程语言语言运行时标准库编译器并发编程Erlang/OTP Logger 配置实战指南从 Cookbook 示例到源码级原理Erlang/OTP Logger 配置实战指南从 Cookbook 示例到源码级原理 导读 Erlang/OTP 自 21.0 起由 Kernel 应用内置编程语言语言运行时标准库编译器并发编程上一篇ComfyUI自定义脚本如何通过UI增强工具提升AI绘画工作流效率下一篇如何系统排查SillyTavern故障从诊断到修复的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
数字标牌广告机驱动板选型指南:主控芯片、电源管理与接口设计 1. 数字标牌广告机驱动板到底是个什么东西1.1 从一台广告机的拆解说起如果你拆过商场里那种竖屏广告机、电梯口的壁挂显示屏,或者奶茶店门口那块滚动菜单的屏幕,你会发现里面其实就三块核心板子:电源板、驱动板、屏。电源板负责把220V交流电变… · 2026/9/24 23:39:49
StyleGAN2卡通人脸微调实战:风格解耦与可控生成 简介:本资源是一份面向深度学习初学者与计算机视觉实践者的卡通人脸生成项目实战包,聚焦StyleGAN2模型微调技术,解决真实人脸到卡通风格图像的跨域转换问题,适用于AI图像生成、艺术风格迁移等应用场景。压缩包共78个文件ÿ… · 2026/9/24 23:39:49
数字标牌广告机驱动板选型指南:从核心构成到实操避坑 1. 数字标牌广告机驱动板到底是个什么东西干了十来年硬件方案,数字标牌这个圈子我算是从里到外摸了个遍。早些年客户拿着一块板子过来,说“这屏点不亮”,我拆开一看,驱动板和屏参压根对不上,TFT时序差了几个时钟周期&a… · 2026/9/24 23:39:49
LibTV新手实战指南:中职生也能90分钟做出参赛级短视频 1. 这不是软件说明书,而是一份“能让你今天就剪出一条像样视频”的实战手记我第一次打开LibTV时,盯着那个灰底蓝框、按钮密密麻麻的界面足足三分钟没敢点——不是因为不会,而是太会了。十年前我用Premiere剪《舌尖上的中国》样片时࿰… · 2026/9/26 5:50:56
工业机器人长时序任务破局:手册理解、符号规划与闭环反馈的多智能体协同框架 1. 工业机器人长时序任务的真实困境与破局思路1.1 为什么“长时序”是工业机器人落地的硬骨头在工业现场待过的人都有一个共识:让机器人完成一个单步动作,比如抓取、放置、拧螺丝,这件事在今天已经相当成熟。真正让人头疼的,是把几… · 2026/9/26 5:50:49
最小二乘法详解:原理、正规方程、Python实现与工程避坑 简介:这份教学课件围绕线性参数的最小二乘法处理展开,面向误差理论、测量数据处理相关课程的学习者,也可供需要掌握数据拟合方法的工程技术人员参考。内容先阐明最小二乘原理——通过使残差平方和最小化,从带随机误差的测量数据中… · 2026/9/26 5:50:43
MySQL+数据可视化实战:从建表到Flask+ECharts大屏搭建 1. 项目思路拆解:为什么要把数据可视化和 MySQL 放在一起学最近后台收到不少私信,都是类似的问题:"我学会了 MySQL 的增删改查,但不知道学来干嘛""数据可视化到底怎么跟数据库打通""为什么招聘要求里总把… · 2026/9/26 5:50:43
五亿token批量生成72个小游戏:流水线设计与工程实践 1. 五亿token到手之后,我为什么选择批量做小游戏拿到智谱赠送的五亿token额度那天,我盯着后台的用量面板看了很久。五亿token是什么概念?按一次对话平均消耗两千token来算,理论上能跑二十五万次请求。如果拿来做代码生成ÿ… · 2026/9/26 5:50:43
分布式数据库系统复习:从分片、事务到故障排查 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 5:50:43
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46