Linux限制用户权限,JSch,ChannelSftp,ChannelExec,java.util.InterruptedException,/etc/ssh/sshd_config,setfacl

1 篇文章 0 订阅
1 篇文章 0 订阅

问题背景:

其他系统在请求我的接口的时候需要拿服务器上的文件,但是我不想给权限比较多的用户。

所以我想在linux上新建一个用户sftpuser,这个用户只能从我提供的目录及子目录下 下载文件,无法进行其他操作,比如登录、上传、修改文件等等。

用户关系:

我一共需要三个用户。

因为我jar包所在服务器和文件服务器是单独的。

jar包接口生成的文件先生成到本地/sftp/files/下,然后通过jsch,channelsftp上传到文件服务器,然后删除本地临时文件。

两个文件服务器用户,一个jar包所在服务器用户。

jar包所在服务器用户jaruser需要/sftp的权限。

chown -R jaruser:jaruser /sftp

一个文件服务器用户fileuser需要/sftp的权限。用来通过jsch,channelsftp创建目录,上传文件,这个用户可以权限多一点,正常一点。

还有一个文件服务器用户就是我要提供给其他系统的用户sftpuser,这个用户只能从我提供的目录及子目录下 下载文件,无法进行其他操作,比如登录、上传、修改文件等等。


切换到root用户

新建用户

useradd sftpuser
passwd sftpuser
# 禁止sftpuser登录。
# 这个现在执行和之后执行都可以,放到最后执行可以登录来测试 setfacl 命令起没起作用。测一下cd,ls之类的。
usermod -s /sbin/nologin sftpuser
mkdir -p /sftp/files/
# 这个文件建哪都行,不影响,只是为了运行个脚本。
vim batchACL.sh

batchACL.sh

#!/bin/bash

# 遍历根目录下的所有目录,但排除/sftp和/目录
directories=($(find / -maxdepth 1 -type d ! -wholename "/sftp" ! -wholename "/" -exec echo {} \;))

# 设置 ACL 条目
for dir in "${directories[@]}"; do
  setfacl -m u:sftpuser:- "$dir"
done
chmod 700 batchACL.sh
./batchACL.sh

我是在自己电脑虚拟机上和服务器上都配置了一遍。有点不同的地方就是同样是用jsch,自己电脑就可以连接,服务器上就无法连接。

Java代码报错,

com.jcraft.jsch.JSchException: java.io.IOException: Pipe closed
Caused by: java.io.IOException:Pipe closed

这时候就需要配置 /etc/ssh/sshd_config

vim /etc/ssh/sshd_config

PasswordAuthentication这个设不设置没影响。

Subsystem       sftp    internal-sftp
Match User sftpuser

在这里插入图片描述

systemctl restart sshd
# 启动生成文件的jar包的用户 (这个我没测,但好像不用chown,不chown也可以在这个目录下生成文件)
chown -R jaruser:jaruser /sftp
# 通过jsch,channelsftp创建目录,上传文件的用户(这个必须chown)
chown -R fileuser:fileuser /sftp

踩坑:

1、网上很多说设置 /etc/ssh/sshd_config 的,我试了无数次,根本无法限制登陆,还能cd到其他目录,总结就是不管用!!!!!!!

还得是 setfacl 这个linux命令简单粗暴。

这个命令的使用可以参考:setfacl linux 命令 在线中文手册 (51yip.com)

setfacl命令 – 设置文件ACL策略规则 – Linux命令大全(手册) (linuxcool.com)

2、究极大大大坑!!!!!!!

如果你在使用jsch,channel相关代码中打了断点,代码报错java.util.InterruptedException,你把断点都取消掉或者不debug就好了。

应该是和超时时间的设置有关,记不太清了,我好像是把session.connect(10000);,channel.connect(10000);这俩都设置的比较大就可以debug不报错了,这样是10秒。

3、这个是大坑,对用户权限不起作用,我不太懂这个文件是干啥的,但是改这个文件对我的需求没有任何帮助。

vim /etc/sudoers

踩坑过程中遇到的一些其他问题。

1、如果想先不设置禁止sftpuser用户登录,看看是否cd不到其他目录之类的,batchACL.sh脚本可以把directories的值改一下。

#!/bin/bash

# 遍历根目录下的所有目录,但排除/D和/目录   /lib64如果不排除,就会报错。
# [root@localhost ~]# su sftpuser
# su: failed to execute /bin/bash: Permission denied
directories=($(find / -maxdepth 1 -type d ! -wholename "/sftp" ! -wholename "/" ! -wholename "/bin" ! -wholename "/lib64" ! -wholename "/home" -exec echo {} \;))

# 设置 ACL 条目
for dir in "${directories[@]}"; do
  setfacl -m u:sftpuser:- "$dir"
done

2、测试 setfacl 命令过程中涉及到的一些命令

# 设置sftpuser对/文件acl规则
setfacl -m u:sftpuser:- /
# 这个-R必须在最前面,清除sftpuser用户,对/文件acl规则
setfacl -R -x u:sftpuser / 
# 清除所有acl
setfacl -b sftpuser 

3、这是用jsch,channelexec进行测试的时候的截图,这个很清晰了,就是说服务只允许sftp连接,为什么呢,因为我配置了ForceCommand internal-sftp
在这里插入图片描述

4、测试用的一些代码。

import com.jcraft.jsch.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

/**
 * <dependency>
 * <groupId>com.jcraft</groupId>
 * <artifactId>jsch</artifactId>
 * <version>0.1.55</version>
 * </dependency>
 * session.connect();,channel.connect();最好设置超时时间,不然默认是无限等待。
 * 加个数字就可以了 session.connect(1000);,channel.connect(1000);,具体多大自己根据实际情况把握。
 */
public class SftpDemo {
    public static void main(String[] args) throws JSchException, SftpException, IOException {
        String host = "192.168.1.200";
        int port = 22;
        String username = "sftpuser";
        String password = "sftpuser";

        JSch jsch = new JSch();
        Session session = jsch.getSession(username, host, port);
        session.setPassword(password);
        // 这个不设置会报错,至于原因不太明白,有兴趣可以研究研究。
        session.setConfig("StrictHostKeyChecking", "no"); 
        session.connect();

        // 打开一个通道
        Channel channel = session.openChannel("exec");
        // 根据;分割,依次执行的。
        String cmd = "cd /sftp;mkdir 3.json;";
        ((ChannelExec) channel).setCommand(cmd);
        InputStream in = channel.getInputStream();
        channel.connect();

        // 读取命令输出
        byte[] buffer = new byte[1024];
        int bytesRead;
        StringBuilder result = new StringBuilder();
        while ((bytesRead = in.read(buffer)) > 0) {
            result.append(new String(buffer, 0, bytesRead));
        }

        // 关闭通道和会话
        channel.disconnect();
        session.disconnect();
        // 打印命令输出
        System.out.println("Command output:\n" + result);


        /*
        ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
        channelSftp.connect();

        String remoteFilePath = "/sftp/upload/1.txt";
//        String remoteFilePath2 = "/opt/software/2.txt";
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        channelSftp.get(remoteFilePath, byteArrayOutputStream);
//        channelSftp.get(remoteFilePath2, byteArrayOutputStream);

        String fileContent = new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8);
        System.out.println("File content:\n" + fileContent);

        channelSftp.disconnect();
        session.disconnect();

         */
    }

}

5、各种命令。

# 监控用户创建、删除、连接等情况。
tailf /var/log/secure

[root@localhost ~]# getent passwd sftpuser
sftpuser:x:1004:1004::/home/sftpuser:/bin/bash
[root@localhost ~]# grep sftpuser /etc/passwd
sftpuser:x:1004:1004::/home/sftpuser:/bin/bash
[root@localhost home]# passwd -u sftpuser
Unlocking password for user sftpuser.
passwd: Success

6、在Linux中,当我们使用mkdir -p /A/B/C/命令创建目录时,如果目录/A/B/C/已经存在,不会对现有目录和文件产生任何不好的影响。这是因为mkdir命令默认会忽略已经存在的目录。

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值