Change SSH port in CentOS with SELinux


Since version 4 of CentOS, SELinux is providing an additional layer of security to the Linux distribution. CentOS describes it like this: “Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) security mechanism implemented in the kernel.” In other words, it controls with rules what a user or process is allowed to do.

从 CentOS 4 开始,SELinux 针对 Linux 发行版提供了一个额外的安全层。CentOS 描述其为:Security-Enhanced Linux(SELinux)是一种在内核中实现的强制访问控制(MAC)安全机制。换句话说,它通过规则控制用户或进程能都被允许做什么。

In my experience, keeping SSH on the default port 22 is a bad idea, as you will notice a lot of login attempts shortly after your server goes online. One of the actions (of course not the only one) to secure the server is to just change this port.

根据我的经验,让 SSH 服务使用默认的 22 端口是一个糟糕的主意,因为在你的服务器上线后不久你就会注意到非常多的尝试登录的记录。其中一种保护服务器安全的方式就是更换默认的 22 端口(当然你不止这一种方式)。

With SELinux in combination with sshd, changing the port, or even listening on 2 ports, is not as easy as just changing the sshd configuration file.

但是当 SELinux 与 sshd 混合使用时,更换端口,甚至监听两个端口,都不像更改 sshd 配置文件那样简单。

First we will need to configure sshd to listen on the new port. As precaution, I’d suggest changing the port in a two step process: first adding the new port to the sshd configuration as a second listening port and in the second step, after verifying that the new port works, removing the old/standard port from the configuration or blocking it via the firewall. For this article lets assume the new port number will be 1234. This is just a number I made up.

首先,我们需要配置 sshd 监听新的端口。为了防止意外,我建议将修改端口分为两个步骤:首先将新端口添加到 sshd 配置中作为第二个监听端口;第二步,在验证新端口工作正常后,从配置中删除旧的默认端口或通过防火墙阻止它。对于本文,假设新端口号为 1234。这只是我编写的数字。

infoYou need to check first that the port number you choose will not be used from any other service you will run on your server. For example, choosing port 80 would be possible but not wise if you want to run a web-server as well. So it’s best to choose a port that is not commonly used for anything else.

首先你需要检查你选择的端口不会被以后在你的服务器上运行的其它任何服务使用。例如,你可以选择端口 80,但如果你想运行一个 web 服务器,这就不明智了。因此,最好选择一个不常用的端口。

Make sure the following lines are in the sshd configuration and none of them is commented out with a leading “#”. In CentOS the ssh server configuration can be found at /etc/ssh/sshd_config.

请确保接下来的几行 sshd 配置没有在开头加上“#”,在 CentOS 中,ssh 服务的配置文件在 /etc/ssh/sshd_config。
Port 22
Port 1234

From sshd’s perspective that should be enough to make it listen on both ports. If you have configured a firewall on your server, make sure the firewall is not blocking the new port.

Now we can restart sshd with the following command:

对于 sshd 来说,这样已经可以同时监听两个端口了。但是如果你在服务器上配置了防火墙的话,请确保防火墙没有阻止新的端口。

现在你可以使用下面的命令重启 sshd 服务了。

$ /etc/init.d/sshd restart

After this you will see that the restart was successful. With the command “lsof -i -P -n” you can check all listening ports. You should see that sshd is not listening on the new port 1234 but still on 22.

A quick look into the logfile will reveal the following messages:

之后你可以看到重启成功了。使用命令“lsof -i -P -n”可以检查所有的监听端口。你会发现 sshd 并没有监听新的端口,而是仍然监听 22 端口。


$ tail /var/log/secure 

Sep 18 13:27:50 server1 sshd[13095]: Received signal 15; terminating.
Sep 18 13:27:50 server1 sshd[13798]: error: Bind to port 1234 on failed: Permission denied.
Sep 18 13:27:50 server1 sshd[13798]: error: Bind to port 1234 on :: failed: Permission denied.
Sep 18 13:27:50 server1 sshd[13798]: Server listening on port 22.
Sep 18 13:27:50 server1 sshd[13798]: Server listening on :: port 22.

This is SELinux in action. SSH is not supposed to listen on port 1234 as far as the SELinux rules are concerned. So we need to modify the SELinux configuration to allow sshd to listen on our new port 1234. To do this, we first need to check what ports sshd is allowed to listen on by executing the following command:

这是 SELinux 的实际操作。对SELinux规则来说,SSH 不应该监听端口 1234。因此,我们需要修改SELinux 配置,以允许 sshd 侦听我们的新端口 1234。要做到这一点,我们首先需要通过执行以下命令来检查允许 sshd 侦听哪些端口

$ semanage port -l | grep ssh

ssh_port_t                     tcp      22

To allow sshd to listen on our new port 1234 we have to add a rule to SELinux. This is done by executing the following command:

为了允许sshd监听我们的新端口 1234,我们必须向 SELinux 添加一条规则。这可以通过执行以下命令来完成。

$ semanage port -a -t ssh_port_t -p tcp 1234

Please be patient while this command is running. It can take some time to finish.


缺少交换空间的问题(Problem with missing swap space)

If you are running a system without swap you might see an error message like this. I found myself in this situation while using an Amazon AWS EC2 micro instance. As you have to pay for every GB of EBS storage, you don’t want to waste it with a huge swap space.

如果你正在运行一个没有交换空间的系统,你可能会看到这样的错误消息。我发现自己在使用 Amazon AWS EC2 微实例时遇到了这种情况。由于需要为每 GB 的 EBS 存储付费,所以您不希望因为巨大的交换空间而浪费它。

libsemanage.semanage_exec_prog: Child process /sbin/setfiles did not exit cleanly.
libsemanage.semanage_install_active: setfiles returned error code -1.
/usr/sbin/semanage: Could not commit semanage transaction

To solve this, first check that swap space is really not available. To do so execute the following command and make sure the line for “swap” shows just the value 0:

要解决这个问题,首先要检查交换空间是否真的不可用。为此,执行以下命令,并确保 swap 行只显示值 0

$ free -t -m

From my experience, a swap space of 32MB should be enough to solve the semanage problem. To create such a swap space file, execute the following command. The first command will create the file with 32MB in size, while the second command will create the swap file-system within this file:

根据我的经验,32MB 的交换空间应该足以解决 semanage 问题。要创建这样一个交换空间文件,可以执行以下命令。第一个命令将创建大小为 32MB 的文件,而第二个命令将在这个文件中创建交换文件系统。

$ dd if=/dev/zero of=/swapfile bs=1024 count=32768
$ mkswap /swapfile

To make sure the owner and permission is correct execute the following:


$ chown root:root /swapfile
$ chmod 0600 /swapfile

Now we can enable the swap space by running this command:


$ swapon /swapfile

Now use this command to add a line to the “/etc/fstab/” file to permanently add this swap space to the server:

现在,使用这个命令在 “/etc/fstab/” 文件中添加一行,将这个交换空间永久地添加到服务器中:

$ echo "/swapfile swap swap defaults 0 0" >> /etc/fstab

After this command has finished we can check the added rule again with the following command:


$ semanage port -l | grep ssh
ssh_port_t                     tcp      1234, 22

It shows that sshd is now allowed to listen on both port 22 and 1234. Now we can restart sshd again and the log-files as well as “lsof -i -P -n” should show that sshd is now listening to both ports. Before we remove port 22 from the configuration file, you should test the login with the new port to ensure that everything works correctly:

它显示现在允许 sshd 侦听端口 22 和 1234。现在我们可以再次重启 sshd,日志文件以及 lsof -i -P -n 应该显示 sshd 现在侦听两个端口。在从配置文件中删除端口 22 之前,您应该使用新端口测试登录,以确保一切正常工作。

$ ssh -p 1234

After successfully logging in to the new port, you can safely remove port 22 from the ssh server configuration file and restart the ssh server, or just block port 22 with the firewall.

成功登录到新端口后,可以安全地从 ssh 服务器配置文件中删除端口 22 并重新启动 ssh 服务器,或者直接用防火墙阻止端口 22。