1.服务介绍
SSH是secure shell protocol的简写,由IETF网络工作小组制定,在进行数据传输之前,SSH先对联机数据包通过加密技术进行加密处理,加密后再进行传输,确保传递的数据安全。
默认状态下,SSH服务主要提供两个服务功能:一个是提供类似telnet远程连接服务器的服务,即SSH服务,另一个类似FTP服务端sftp-server,借助SSH协议来传输数据的,提供更安全的SFTP服务。
提醒:ssh客户端还包含一个很有用的远程安全拷贝命令SCP,也是通过ssh协议工作的。
ssh的工作机制大致是本地ssh客户端先发送一个连接请求到远程的ssh服务端,服务端检查连接的客户端发送到数据包和IP地址,如果确认合法,就会发送密钥给ssh给客户端,此时,客户端本地再将密钥发回给服务端,自此连接建立
2.远程连接过程
ssh客户端
openssh-client
xshell/secureCRT/putty/finalshell …….
[root@dmxsp ~]# rpm -qa | grep openssh
openssh-clients-7.4p1-21.el7.x86_64
openssh-server-7.4p1-21.el7.x86_64
openssh-7.4p1-21.el7.x86_64
linux互相连接过程
第一次连接
[root@dmxsp ~]# ssh 172.16.1.8
The authenticity of host ‘172.16.1.8 (172.16.1.8)’ can’t be established.
ECDSA key fingerprint is SHA256:HPnpdimIQY/ffHz814mUh16PmTB1MMFY0WI0EECtWHg.
ECDSA key fingerprint is MD5:e3:d0:2e:7f:08:db:d4:c6:6d:35:74:1e:26:c2:91:6b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘172.16.1.8’ (ECDSA) to the list of known hosts.
root@172.16.1.8’s password:
Last login: Thu Jul 21 20:08:06 2022 from 172.16.1.22
[root@web02 ~]$
第一次连接需要记录这台机器的指纹信息
[root@dmxsp ~]#ll -a
drwx—— 2 root root 48 Jun 7 2021 .ssh
[root@dmxsp ~]# ll .ssh/known_hosts
-rw-r–r– 1 root root 866 Jun 15 2021 .ssh/known_hosts
端口
SSH是安全的加密协议,用于远程连接linux服务器。
SSH默认端口是22,安全协议版本SSH2,除了2之外还有SSH1(有漏洞)。
SSH服务端主要包含两个服务功能SSH远程连接和SFTP服务。
Linux SSH客户端包含ssh远程连接命令,以及远程拷贝scp命令等
3.telnet vs ssh
ssh 加密(密文)
telnet 未加密(明文)
安装telnet
[root@dmxsp ~]# yum install -y telnet-server
查看配置文件
[root@dmxsp ~]# rpm -ql telnet-server
/usr/lib/systemd/system/telnet.socket
/usr/lib/systemd/system/telnet@.service
/usr/sbin/in.telnetd
/usr/share/man/man5/issue.net.5.gz
/usr/share/man/man8/in.telnetd.8.gz
/usr/share/man/man8/telnetd.8.gz
启动服务
[root@dmxsp ~]# systemctl restart telnet.socket
测试(不让root用户登录,使用普通用户)
[c:\~]$ telnet 10.0.0.22 23
Connecting to 10.0.0.22:23…
Connection established.
To escape to local shell, press ‘Ctrl+Alt+]’.
Kernel 3.10.0-1127.el7.x86_64 on an x86_64
dmxsp login: qwer
Password:
4.ssh密钥认证
原理
生成密钥对—把公钥(公钥以.pub结尾)发送—修改名字修改权限—客户端发送连接请求服务端验证密钥—
5.密钥认证
ssh-keygen
生成、管理和转换认证密钥
-b:指定密钥长度
-B:显示指定的公钥/私钥文件的 bubblebabble 摘要
-e:读取openssh的私钥或者公钥文件
-C:添加注释
-c:要求修改私钥和公钥文件中的注释。本选项只支持 RSA1 密钥。 程序将提示输入私钥文件名、密语(如果存在)、新注释
-D:下载存储在智能卡 reader 里的 RSA 公钥
-F hostname:在 known_hosts 文件中搜索指定的 hostname ,并列出所有的匹配项。这个选项主要用于查找散列过的主机名/ip地址,还可以和 -H 选项联用打印找到的公钥的散列值
-f:指定用来保存密钥的文件名
-i:读取未加密的ssh-v2兼容的私钥/公钥文件,然后在标准输出设备上显示openssh兼容的私钥/公钥
-l:显示公钥文件的指纹数据
-N:提供一个新密语
-P:提供(旧)密语
-q:静默模式
-t:指定要创建的密钥类
ssh-copy-id
命令可以把本地主机的公钥复制到远程主机的authorized_keys文件上,ssh-copy-id命令也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限
-i:指定认证文件(公钥)
-f:强制模式
-n:测试,不实际替换
-p port:指定端口
-o option:指定其他 ssh 参数
ssh
ssh 用于登录远程主机, 并且在远程主机上执行命令. 它的目的是替换 rlogin 和 rsh, 同时在不安全的网络之上, 两个互不 信任的主机之间, 提供加密的, 安全的通信连接. X11 连接和任意 TCP/IP 端口均可以通过此安全通道转发(forward).当用户通过 连接并登录主机 hostname 后, 根据所用的协议版本, 用户必须通过下述方法之一向远程主机证明他/她的身份
-a:禁止转发认证代理的连接
-b:在拥有多个接口或地址别名的机器上, 指定收发接口
-c blowfish|3des|des:选择加密会话的密码术. 3des 是默认算法. 3des (triple-des) 用三支不同的密钥做加密-解密-加密三次运算, 被认为比较可靠. blowfish 是一种快速的分组加密术(block cipher), 非常安全, 而且速度比 3des 快的多. des 仅支持 客户端, 目的是能够和老式的不支持 3des 的协议第一版互操作. 由于其密码算法上的弱点, 强烈建议避免使用
-e ch|^ch|none:设置 pty 会话的 escape 字符 (默认字符: `~’ ) . escape 字符只在行首有效, escape 字符后面跟一个点 (`.’ ) 表示结束连接, 跟一个 control-Z 表示挂起连接(suspend), 跟 escape 字符自己 表示输出这个字符. 把这个字符设为 “none 则禁止 escape 功能, 使会话完全透明
-o:可以在这里给出某些选项, 格式和配置文件中的格式一样. 它用来设置那些没有命令行开关的选项
-f:要求 在执行命令前退至后台. 它用于当 准备询问口令或密语, 但是用户希望它在后台进行. 该选项隐含了 -n 选项. 在远端机器上启动 X11 程序的推荐手法就是类似于 ssh -f host xterm 的命令
-g:允许远端主机连接本地转发的端口
-i:指定一个 RSA 或 DSA 认证所需的身份(私钥)文件. 默认文件是协议第一版的 $HOME/.ssh/identity 以及协议第二版的 $HOME/.ssh/id_rsa 和 $HOME/.ssh/id_dsa 文件. 也可以在配置文件中对每个主机单独指定身份文件. 可以同时使用多个 -i 选项 (也可以在配置文件中指定多个身份文件
-l:指定登录远程主机的用户. 可以在配置文件中对每个主机单独设定这个参数
-n:把 stdin 重定向到 /dev/null (实际上防止从 stdin 读取数据). 在后台运行时一定会用到这个选项. 它的常用技巧是远程运行 X11 程序. 例如, ssh -n shadows.cs.hut.fi emacs 将会在 shadows.cs.hut.fi 上启动 emacs, 同时自动在加密通道中转发 X11 连接. 在后台运行. (但是如果 要求口令或密语, 这种方式就无法工作; 参见 -f 选项.
-N:不执行远程命令. 用于转发端口
-p:指定远程主机的端口. 可以在配置文件中对每个主机单独设定这个参数
-q:安静模式. 消除所有的警告和诊断信息
-t:强制分配伪终端. 可以在远程机器上执行任何全屏幕(screen-based)程序, 所以非常有用, 例如菜单服务. 并联的 -t 选项强制分配终端, 即使 没有本地终端
-F:指定一个用户级配置文件. 如果在命令行上指定了配置文件, 系统级配置文件 (/etc/ssh/ssh_config ) 将被忽略. 默认的用户级配置文件是 $HOME/.ssh/config
-v:冗详模式. 使 打印关于运行情况的调试信息. 在调试连接, 认证和配置问题时非常有用. 并联的 -v 选项能够增加冗详程度. 最多为三个
-1:强制 只使用协议第一版.
-2:强制 只使用协议第二版.
-4:强制 只使用 IPv4 地址.
-6:强制 只使用 IPv6 地址
sftp
可以通过ssh来上传和下载文件,是常用的文件传输工具,它的使用方式与ftp类似,但它使用ssh作为底层传输协议,所以安全性比ftp要好得多
格式:sftp <host>
通过sftp连接<host>,端口为默认的22,用户为Linux当前登录用户。
格式:sftp -oPort=<port> <host>
通过sftp连接<host>,指定端口<port>,用户为Linux当前登录用户。
格式:sftp <user>@<host>
通过sftp连接<host>,端口为默认的22,指定用户<user>。
格式:sftp -oPort=<port> <user>@<host>
通过sftp连接<host>,端口为<port>,用户为<user>
cd:路径 更改远程目录到“路径”
lcd:路径 更改本地目录到“路径”
chgrp group path:将文件“path”的组更改为“group”
chmod mode path:将文件“path”的权限更改为“mode”
chown owner path:将文件“path”的属主更改为“owner”
exit:退出 sftp
help:显示这个帮助文本
get:远程路径 下载文件
ln existingpath linkpath:符号链接远程文件
ls [选项] [路径]:显示远程目录列表
lls [选项] [路径]:显示本地目录列表
mkdir:路径 创建远程目录
lmkdir:路径 创建本地目录
mv oldpath newpath:移动远程文件
open:[用户@]主机[:端口] 连接到远程主机
put:本地路径 上传文件
pwd:显示远程工作目录
lpwd:打印本地工作目录
quit:退出 sftp
rmdir:路径 移除远程目录
lrmdir:路径 移除本地目录
rm:路径 删除远程文件
lrm:路径 删除本地文件
symlink existingpath linkpath:符号链接远程文件
version:显示协议版本
scp
在主机间复制文件。他使用 ssh(1)作为数据传输。而且用同样认证和安全性。 scp将在认证中请求输入密码所有的文件可能需要服务器和用户的特别描述来指明文件将被复制到/从某台服务器。两个远程登录的服务器间的文件复制是允许的
-1:强制scp 用协议1
-2:强制scp 用协议2
-4:强制scp用IPV4的网址
-6:强制scp用IPV6的网址
-B:选择批处理模式(防止输入密码)
-C:允许压缩。 标注-C到ssh(1)来允许压缩
-c:cipher选择cipher来加密数据传输。这个选项直接传递到ssh(1)
-F:ssh_config设定一个可变动的用户配置给ssh.这个选项直接会被传递到ssh(1)
-i:identity_file选择被RSA认证读取私有密码的文件。这个选项可以直接被传递到ssh(1)
-l:limit限制传输带宽,也就是速度 用KByte/s的速度
-o:ssh_option 可以把ssh_config中的配置格式传到ssh中。这种模式对于说明没有独立的scp文件中断符的scp很有帮助。关于选项的如下。而他们的值请参看ssh_config(5)
-P:port 指定连接远程连接端口。注意这个选项需要写成大写的模式。因为-p已经早保留了次数和模式
-S:program 指定一个加密程序。这个程序必须可读所有ssh(1)的选项。
-p:指定修改次数,连接次数,还有对于原文件的模式
-q:把进度参数关掉
-r:递归的复制整个文件夹
-S:program 指定一个加密程序。这个程序必须可读所有ssh(1)的选项。
-V:冗余模式。 让 scp 和 ssh(1) 打印他们的排错信息, 这个在排错连接,认证,和配置中非常有用
sshpass
是一个简单、轻量级的命令行工具,通过它我们能够向命令提示符本身提供密码(非交互式密码验证),这样就可以通过 cron 调度器执行自动化的 shell 脚本进行备份
-f filename:从文件中获取密码
-d number:使用数字作为获取密码的文件描述符
-p password:指定明文本密码输入(安全性较差)
-e 从环境变量SSHPASS获取密码
密钥类型
dsa(老的)
rsa(新的)
DSA和RSA的区别
DSA是基于整数有限域离散对数难题的,DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到。
RSA算法在网络容易实现密钥管理,便进行数字签名,算法复杂,加/解速度慢,采用非对称加密
DSA 用于签名,而 RSA 可用于签名和加密。
RSA的安全性一直未能得到理论上的证明。 RSA的安全性依赖于大数分解。公钥和私钥都是两个大素数( 大于 100个十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
环境准备
管理机
[root@sshd ~]$ hostname -I
10.0.0.13 172.16.1.13
被管理机
[root@sshd-01 ~]$ hostname -I
10.0.0.113 172.16.1.113
[root@sshd-02 ~]$ hostname -I
10.0.0.213 172.16.1.213
创建密钥对
[root@sshd ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): #默认.ssh目录,如果目录不存在会自动创建
Enter passphrase (empty for no passphrase): #加只读密码 按回车密码为空
Enter same passphrase again: #确认
Your identification has been saved in /root/.ssh/id_rsa. #私钥的位置及名字
Your public key has been saved in /root/.ssh/id_rsa.pub. #公钥的位置及名字,公钥是以.pub结尾的(默认)
The key fingerprint is:
SHA256:LR3OlI85m1ZcdcCMa4/IQYSorhn9EmJ8Fl3BR7lGVYw root@sshd
The key’s randomart image is:
+—[RSA 2048]—-+
| o.=oo.Bo.o|
| . + =.E +..|
| o . ++. .. |
| o . *+*o. |
| . o . SoO++o |
| = * .o=. . |
| . B o + |
| o . . . |
| . |
+—-[SHA256]—–+
查看目录
[root@sshd ~]$ ll .ssh/
total 8
-rw——- 1 root root 1679 Jul 22 16:36 id_rsa
-rw-r–r– 1 root root 391 Jul 22 16:36 id_rsa.pub
分发密钥(公钥)
默认为root用户,如果想要发布到其它用户加上nginx@172.16.1.113
[root@sshd ~]$ ssh-copy-id -i /root/.ssh/id_rsa.pub 172.16.1.113
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”
The authenticity of host ‘172.16.1.113 (172.16.1.113)’ can’t be established.
ECDSA key fingerprint is SHA256:HPnpdimIQY/ffHz814mUh16PmTB1MMFY0WI0EECtWHg.
ECDSA key fingerprint is MD5:e3:d0:2e:7f:08:db:d4:c6:6d:35:74:1e:26:c2:91:6b.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
root@172.16.1.113’s password:
Number of key(s) added: 1
Now try logging into the machine, with: “ssh ‘172.16.1.113’”
and check to make sure that only the key(s) you wanted were added.
测试
[root@sshd ~]$ ssh 172.16.1.113
Last login: Fri Jul 22 12:29:11 2022
[root@sshd-01 ~]$ hostname -I
10.0.0.113 172.16.1.113
查看113机器上.ssh目录
[root@sshd-01 ~]$ ll .ssh/
total 4
-rw——- 1 root root 391 Jul 22 18:09 authorized_keys
查看.ssh目录下的文件是否一致
ssh-copy-id 原理
[root@sshd ~]$ vim /bin/ssh-copy-id
295 ssh “$@” “exec sh -c ‘cd ; umask 077 ; mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorec
on -F .ssh .ssh/authorized_keys ; fi'” \
解释
进入当前用户家目录
cd
修改系统的umask 077; 创建文件600 ,目录700
umask 077
创建目录
mkdir -p .ssh
把创建公钥内容追加到 .ssh/authorized_keys 文件中
cat >> .ssh/authorized_keys
6.ssh服务端配置
安全要求高的场景会禁用密码登录, 只开启秘钥认证
[root@sshd ~]$ egrep -n “PubkeyAuthentication|PasswordAuthentication” /etc/ssh/sshd_config
43:#PubkeyAuthentication yes #是否开启秘钥认证
63:#PasswordAuthentication yes #是否开启密码认证(登录)
配置文件
ssh连接默认端口为22,这都知道。因此,为提高安全级别,建议改掉它
[root@sshd ~]$ egrep -n “Port” /etc/ssh/sshd_config
17:#Port 22
root超级用户都知道,建议禁止它远程登陆能力
[root@sshd ~]$ egrep -n “PermitRootLogin” /etc/ssh/sshd_config
38:#PermitRootLogin yes
禁止空密码登陆
[root@sshd ~]$ egrep -n “PermitEmptyPasswords” /etc/ssh/sshd_config
64:#PermitEmptyPasswords no
是否允许密码登录
[root@sshd ~]$ egrep -n “PasswordAuthentication” /etc/ssh/sshd_config
63:#PasswordAuthentication yes
是否允许密钥认证
[root@sshd ~]$ egrep -n “PubkeyAuthentication” /etc/ssh/sshd_config
43:#PubkeyAuthentication yes
如果开启密码登录这里要是yes
[root@sshd ~]$ egrep -n “UsePAM” /etc/ssh/sshd_config
96:UsePAM yes
连接速度
远程连接的ip地址—>解析为域名
[root@sshd ~]$ egrep -n “UseDNS|GSSAPIAuthentication” /etc/ssh/sshd_config
79:GSSAPIAuthentication no
115:UseDNS no
监听地址
[root@sshd ~]$ egrep -n “ListenAddress” /etc/ssh/sshd_config
19:#ListenAddress 0.0.0.0
20:#ListenAddress ::
需求
让用户只能通过内网的ip连接服务器 ,无法通过公网ip连接进来
实现
1.关闭公网网卡
2.使用防火墙控制
3.使用sshd_config ListenAddress
ListenAddress 172.16.1.13
7.ssh客户端命令
括号里的是不加密的
ssh(telnet)
sftp(ftp)
scp(rcp)
ssh
指定端口号
[root@sshd ~]$ ssh -p22 172.16.1.113
指定用户,ssh连接默认使用当前用户(这个用户不会直接连接,因为没有给这个用户配密钥)
[root@sshd ~]$ ssh dmxsp@10.0.0.113
连接的时候不验证主机密钥
[root@sshd ~]$ ssh -o StrictHostKeyChecking=no dmxsp@10.0.0.113
sftp
sftp linux中ftp客户端
xftp windows中的ftp客户端
交互式
[root@sshd ~]$ sftp 172.16.1.113
Connected to 172.16.1.113.
sftp> ls
Centos-7.repo anaconda-ks.cfg epel-7.repo
查看可以使用的命令
sftp> help Available commands: bye Quit sftp cd path Change remote directory to 'path' chgrp grp path Change group of file 'path' to 'grp' chmod mode path Change permissions of file 'path' to 'mode' chown own path Change owner of file 'path' to 'own' df [-hi] [path] Display statistics for current directory or filesystem containing 'path' exit Quit sftp get [-afPpRr] remote [local] Download file reget [-fPpRr] remote [local] Resume download file reput [-fPpRr] [local] remote Resume upload file help Display this help text lcd path Change local directory to 'path' lls [ls-options [path]] Display local directory listing lmkdir path Create local directory ln [-s] oldpath newpath Link remote file (-s for symlink) lpwd Print local working directory ls [-1afhlnrSt] [path] Display remote directory listing lumask umask Set local umask to 'umask' mkdir path Create remote directory progress Toggle display of progress meter put [-afPpRr] local [remote] Upload file pwd Display remote working directory quit Quit sftp rename oldpath newpath Rename remote file rm path Delete remote file rmdir path Remove remote directory symlink oldpath newpath Symlink remote file version Show SFTP version !command Execute 'command' in local shell ! Escape to local shell ? Synonym for help
非交互式
[root@sshd ~]$ cat upload.ftp
put /etc/hosts /tmp
put -r /etc /opt
get /etc/hostname /root
[root@sshd ~]$ sftp -b upload.ftp 172.16.1.113
scp
传输文件
[root@sshd ~]$ scp -P22 /etc/passwd 172.16.1.113:/mnt/
passwd 100% 1057 1.8MB/s 00:00
8.批量分发密钥
非交互发送密钥到1台机器
免交互创建密钥对
[root@sshd ~]$ ssh-keygen -t rsa -f /root/.ssh/id_rsa -P ”
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:jaQg2mkGgueXcF01dI4XaNljXAo+h/g2opmzxXZCaSk root@sshd
The key’s randomart image is:
+—[RSA 2048]—-+
| .o==o.. |
|. . . o+B=o |
|+ + o . o.=.=. |
|.* = o o * + |
|. * o E S = |
| o . O o . |
| = = . |
| = o |
| . |
+—-[SHA256]—–+
非交互式分发密钥对
[root@sshd ~]$ ssh-copy-id -i /root/.ssh/id_rsa.pub -o StrictHostKeyChecking=no -p22 172.16.1.113
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
root@172.16.1.113’s password:
Number of key(s) added: 1
Now try logging into the machine, with: “ssh -o ‘StrictHostKeyChecking=no’ -p ’22’ ‘172.16.1.113’”
and check to make sure that only the key(s) you wanted were added.
非交互式输入密码
安装sshpass
[root@sshd ~]$ yum install -y sshpass
[root@sshd ~]$ sshpass -p1 ssh-copy-id -i /root/.ssh/id_rsa.pub -o StrictHostKeyChecking=no -p22 172.16.1.113
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: “ssh -o ‘StrictHostKeyChecking=no’ -p ’22’ ‘172.16.1.113’”
and check to make sure that only the key(s) you wanted were added.
批量发送
循环脚本
[root@sshd ~]$ cat sshd.sh
for ip in {113,213}
do
sshpass -p1 ssh-copy-id -i /root/.ssh/id_rsa.pub -o StrictHostKeyChecking=no -p22 172.16.1.$ip
done
[root@sshd ~]$ sh sshd.sh
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: “ssh -o ‘StrictHostKeyChecking=no’ -p ’22’ ‘172.16.1.113’”
and check to make sure that only the key(s) you wanted were added.
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: “ssh -o ‘StrictHostKeyChecking=no’ -p ’22’ ‘172.16.1.213’”
and check to make sure that only the key(s) you wanted were added.