mirror of
https://github.com/LamGC/Oracle-Sentry.git
synced 2025-04-29 22:27:34 +00:00
feat: 初步添加 SSH Forwarding 功能.
添加对 SSH 转发功能的支持, 脚本可通过 SSH 会话使用. 注意: 该功能尚未得到足够的测试, 使用时遇到问题请反馈.
This commit is contained in:
parent
3641593210
commit
13d90595b7
@ -107,6 +107,7 @@ class ApplicationInitiation {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@Order(1)
|
@Order(1)
|
||||||
|
@SuppressWarnings({"MismatchedReadAndWriteOfArray", "RedundantOperationOnEmptyContainer"})
|
||||||
private void initialEnvironment() throws IOException {
|
private void initialEnvironment() throws IOException {
|
||||||
String[] directors = new String[] {
|
String[] directors = new String[] {
|
||||||
"./config",
|
"./config",
|
||||||
@ -115,7 +116,7 @@ class ApplicationInitiation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
String[] files = new String[] {
|
String[] files = new String[] {
|
||||||
sshIdentityPath
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (String directory : directors) {
|
for (String directory : directors) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.lamgc.oracle.sentry;
|
package net.lamgc.oracle.sentry;
|
||||||
|
|
||||||
|
import net.lamgc.oracle.sentry.oci.compute.ssh.ConfiguredForwardingFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -23,6 +25,8 @@ public final class Constants {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private String firstConnectionPolicy;
|
private String firstConnectionPolicy;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfiguredForwardingFilter forwardingFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 SSH 首次连接策略.
|
* 获取 SSH 首次连接策略.
|
||||||
@ -32,4 +36,12 @@ public final class Constants {
|
|||||||
public String getFirstConnectionPolicy() {
|
public String getFirstConnectionPolicy() {
|
||||||
return firstConnectionPolicy;
|
return firstConnectionPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已配置的转发过滤器.
|
||||||
|
* @return 返回转发过滤器.
|
||||||
|
*/
|
||||||
|
public ConfiguredForwardingFilter getForwardingFilter() {
|
||||||
|
return forwardingFilter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
||||||
|
|
||||||
|
import org.apache.sshd.common.session.Session;
|
||||||
|
import org.apache.sshd.common.util.net.SshdSocketAddress;
|
||||||
|
import org.apache.sshd.server.forward.ForwardingFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已配置转发过滤器.
|
||||||
|
* <p> 根据应用配置, 选择是否允许转发指定类型的流量.
|
||||||
|
* @author LamGC
|
||||||
|
*/
|
||||||
|
@Component("sentry.script.ssh.forwarding.filter")
|
||||||
|
public class ConfiguredForwardingFilter implements ForwardingFilter {
|
||||||
|
|
||||||
|
@Value("oracle.ssh.forwarding.X11.enable")
|
||||||
|
private String x11Enabled;
|
||||||
|
|
||||||
|
@Value("oracle.ssh.forwarding.tcp.enable")
|
||||||
|
private String tcpEnabled;
|
||||||
|
|
||||||
|
@Value("oracle.ssh.forwarding.agent.enable")
|
||||||
|
private String agentEnabled;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canForwardAgent(Session session, String requestType) {
|
||||||
|
return Boolean.parseBoolean(agentEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canListen(SshdSocketAddress address, Session session) {
|
||||||
|
return Boolean.parseBoolean(tcpEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canConnect(Type type, SshdSocketAddress address, Session session) {
|
||||||
|
return Boolean.parseBoolean(tcpEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canForwardX11(Session session, String requestType) {
|
||||||
|
return Boolean.parseBoolean(x11Enabled);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import net.lamgc.oracle.sentry.Constants;
|
||||||
import net.lamgc.oracle.sentry.oci.compute.ComputeInstance;
|
import net.lamgc.oracle.sentry.oci.compute.ComputeInstance;
|
||||||
import org.apache.sshd.client.SshClient;
|
import org.apache.sshd.client.SshClient;
|
||||||
import org.apache.sshd.client.future.AuthFuture;
|
import org.apache.sshd.client.future.AuthFuture;
|
||||||
@ -40,6 +41,7 @@ public class InstanceSsh implements AutoCloseable {
|
|||||||
this.authInfo = Objects.requireNonNull(authInfo);
|
this.authInfo = Objects.requireNonNull(authInfo);
|
||||||
|
|
||||||
sshClient = SshClient.setUpDefaultClient();
|
sshClient = SshClient.setUpDefaultClient();
|
||||||
|
sshClient.setForwardingFilter(Constants.instance.getForwardingFilter());
|
||||||
sshClient.setServerKeyVerifier(new OracleInstanceServerKeyVerifier(instance, authInfo));
|
sshClient.setServerKeyVerifier(new OracleInstanceServerKeyVerifier(instance, authInfo));
|
||||||
if (authInfo instanceof PublicKeyAuthInfo info) {
|
if (authInfo instanceof PublicKeyAuthInfo info) {
|
||||||
sshClient.setKeyIdentityProvider(new FileKeyPairProvider(info.getPrivateKeyPath().toPath()));
|
sshClient.setKeyIdentityProvider(new FileKeyPairProvider(info.getPrivateKeyPath().toPath()));
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
||||||
|
|
||||||
import org.apache.sshd.client.session.ClientSession;
|
import org.apache.sshd.client.session.ClientSession;
|
||||||
|
import org.apache.sshd.client.session.forward.ExplicitPortForwardingTracker;
|
||||||
|
import org.apache.sshd.common.util.net.SshdSocketAddress;
|
||||||
import org.apache.sshd.sftp.client.SftpClientFactory;
|
import org.apache.sshd.sftp.client.SftpClientFactory;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
@ -45,6 +47,31 @@ public class SshSession implements Closeable {
|
|||||||
return new SftpSession(factory.createSftpClient(clientSession));
|
return new SftpSession(factory.createSftpClient(clientSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建本地 TCP 转发隧道.
|
||||||
|
* <p> 该隧道为方向为 "本地->远端" (本地发起连接转发至远端端口).
|
||||||
|
* @return 返回 TCP 转发通道对象, 可获取通道信息和关闭通道.
|
||||||
|
*/
|
||||||
|
public TcpForwardingChannel createLocalTcpForwarding(int localPort, int remotePort) throws IOException {
|
||||||
|
ExplicitPortForwardingTracker tracker = clientSession
|
||||||
|
.createLocalPortForwardingTracker(localPort, new SshdSocketAddress(remotePort));
|
||||||
|
return new TcpForwardingChannel(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建远端 TCP 转发隧道.
|
||||||
|
* <p> 该隧道为方向为 "本地<-远端" (远端服务器发起连接转发至本地端口).
|
||||||
|
* @param remotePort 远端监听端口号, 该端口为远端服务连接转发的端口号.
|
||||||
|
* @param localPort 本地连接端口号, 该端口为本地服务端的端口号.
|
||||||
|
* @return 返回 Tcp 转发通道对象, 用于管理转发通道.
|
||||||
|
*/
|
||||||
|
public TcpForwardingChannel createRemoteTcpForwarding(int remotePort, int localPort) throws IOException {
|
||||||
|
ExplicitPortForwardingTracker tracker =
|
||||||
|
clientSession.createRemotePortForwardingTracker(
|
||||||
|
new SshdSocketAddress(remotePort), new SshdSocketAddress(localPort));
|
||||||
|
return new TcpForwardingChannel(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭 SSH 连接会话, 该连接会话所属的其他会话将会一同被关闭.
|
* 关闭 SSH 连接会话, 该连接会话所属的其他会话将会一同被关闭.
|
||||||
* @throws IOException 关闭失败时抛出异常,
|
* @throws IOException 关闭失败时抛出异常,
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package net.lamgc.oracle.sentry.oci.compute.ssh;
|
||||||
|
|
||||||
|
import org.apache.sshd.client.session.forward.ExplicitPortForwardingTracker;
|
||||||
|
import org.apache.sshd.common.util.net.SshdSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TCP 隧道.
|
||||||
|
* <p> 可通过该对象管理隧道.
|
||||||
|
* @author LamGC
|
||||||
|
*/
|
||||||
|
public class TcpForwardingChannel implements AutoCloseable {
|
||||||
|
|
||||||
|
private final ExplicitPortForwardingTracker tracker;
|
||||||
|
|
||||||
|
TcpForwardingChannel(ExplicitPortForwardingTracker tracker) {
|
||||||
|
this.tracker = tracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为本地转发.
|
||||||
|
* @return 如果是本地转发, 则为 {@code true}, 否则返回 {@code false}, 代表远端转发.
|
||||||
|
*/
|
||||||
|
public boolean isLocalForwarding() {
|
||||||
|
return tracker.isLocalForwarding();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隧道是否已打开.
|
||||||
|
* @return 如果已经打开, 返回 {@code true}, 否则返回 {@code false} 表示已关闭.
|
||||||
|
*/
|
||||||
|
public boolean isOpen() {
|
||||||
|
return tracker.isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本地地址.
|
||||||
|
* @return 获取本地连接地址.
|
||||||
|
*/
|
||||||
|
public SshdSocketAddress getLocalAddress() {
|
||||||
|
return tracker.getLocalAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取远端地址.
|
||||||
|
* @return 获取远端地址.
|
||||||
|
*/
|
||||||
|
public SshdSocketAddress getRemoteAddress() {
|
||||||
|
return tracker.getRemoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取监听绑定地址.
|
||||||
|
* @return 返回监听绑定地址.
|
||||||
|
*/
|
||||||
|
public SshdSocketAddress getBoundAddress() {
|
||||||
|
return tracker.getBoundAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
|
tracker.close();
|
||||||
|
}
|
||||||
|
}
|
@ -14,3 +14,14 @@ oracle:
|
|||||||
# 首次连接认证策略
|
# 首次连接认证策略
|
||||||
# 支持 confirm(询问) accept(接受) reject(拒绝)
|
# 支持 confirm(询问) accept(接受) reject(拒绝)
|
||||||
authenticationPolicy: 'confirm'
|
authenticationPolicy: 'confirm'
|
||||||
|
# SSH 转发设定
|
||||||
|
forwarding:
|
||||||
|
# X11 转发
|
||||||
|
X11:
|
||||||
|
enable: false
|
||||||
|
# SSH-Agent 转发
|
||||||
|
agent:
|
||||||
|
enable: false
|
||||||
|
# TCP 转发
|
||||||
|
tcp:
|
||||||
|
enable: true
|
||||||
|
Loading…
Reference in New Issue
Block a user