如何使用java与防火墙(路由器)建立ssh连接? [英] How to make a ssh connection to a firewall(router) with java?

查看:227
本文介绍了如何使用java与防火墙(路由器)建立ssh连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于某种原因,我需要连接到防火墙(基于Linux)并使用Java添加一些规则。



在谷歌搜索了一段时间后,我发现 jsch 是我的最佳选择。但是当我 b
$ b

使用它执行命令时, show hostname 例如,返回错误。如果我



执行ls -lwhoami等命令,结果还可以。那就是说,我只能



连接到Bash Shell!我的问题是如何连接防火墙shell?



我的测试代码如下:

  import java.io.InputStream; 

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

公共类SSHDemo {
public static void main(String [] args){
SSHDemo t = new SSHDemo();
try {
t.go();
} catch(Exception ex){
ex.printStackTrace();
}
}

public void go()throws Exception {
String host =10.4.44.192;
String user =root;
String password =root;
int port = 22;
// int tunnelLocalPort = 9080;
//字符串tunnelRemoteHost =10.4.44.192;
// int tunnelRemotePort = 8000;
JSch jsch = new JSch();
会话session = jsch.getSession(用户,主机,端口);
session.setPassword(密码);
localUserInfo lui = new localUserInfo();
session.setUserInfo(lui);
session.connect();

ChannelExec channel =(ChannelExec)session.openChannel(exec);
channel.setInputStream(null);

//支付此行的罚款
channel.setCommand(show hostname);
channel.setErrStream(System.err);
channel.connect();
InputStream in = channel.getInputStream();
int i = 0;
byte [] tmp = new byte [1024 * 1024];
while((i = in.read(tmp,0,tmp.length))!= -1){
System.out.write(tmp,0,i);
}
in.close();


channel.disconnect();
session.disconnect();
// session.setPortForwardingL(tunnelLocalPort,tunnelRemoteHost,tunnelRemotePort);
System.out.println(已连接);

}


class localUserInfo实现UserInfo {
String passwd;

public String getPassword(){
return passwd;
}

public boolean promptYesNo(String str){
return true;
}

public String getPassphrase(){
return null;
}

public boolean promptPassphrase(String message){
return true;
}

public boolean promptPassword(String message){
return true;
}

public void showMessage(String message){
}
}
}


解决方案

尝试使用 ChannelShell 打开 shell 而不是 exec



以下是用于登录和执行远程java类文件的小代码示例。

  private Expect4j SSH(String hostname,String username,String password,int port)抛出异常{
JSch jsch =新的JSch();
会话session = jsch.getSession(用户名,主机名,端口);
if(密码!= null){
session.setPassword(密码);
}
Hashtable< String,String> config = new Hashtable< String,String>();
config.put(StrictHostKeyChecking,no);
session.setConfig(config);
session.connect(60000);
channel =(ChannelShell)session.openChannel(shell);
Expect4j expect = new Expect4j(channel.getInputStream(),channel.getOutputStream());
channel.connect();
返回预期;
}

此方法将打开SSH流到远程服务器,expect4j将使用它用于发送命令。

  private boolean executeCommands(){
boolean isSuccess = true;
Closure closure = new Closure(){
public void run(ExpectState expectState)throws Exception {
buffer.append(expectState.getBuffer()); // buffer是字符串缓冲区,用于附加输出执行命令
expectState.exp_continue();
}
};
列表<匹配> lstPattern = new ArrayList< Match>();
String [] regEx = SSHConstants.linuxPromptRegEx;
if(regEx!= null&& regEx.length> 0){
synchronized(regEx){
for(String regexElement:regEx){// list of regx like, :>,/>您可以使用远程机器的命令提示
try {
RegExpMatch mat = new RegExpMatch(regexElement,closure);
lstPattern.add(mat);
} catch(MalformedPatternException e){
return false;
} catch(异常e){
返回false;
}
}
lstPattern.add(新的EofMatch(new Closure(){//应该导致整个页面被收集
public void run(ExpectState state){
}
}));
lstPattern.add(new TimeoutMatch(defaultTimeOut,new Closure(){
public void run(ExpectState state){
}
}));
}
}
try {
Expect4j expect = SSH(objConfig.getHostAddress(),objConfig.getUserName(),objConfig.getPassword(),SSHConstants.SSH_PORT);
expect.setDefaultTimeout(defaultTimeOut);
if(isSuccess){
for(String strCmd:lstCmds)
isSuccess = isSuccess(lstPattern,strCmd);
}
boolean isFailed = checkResult(expect.expect(lstPattern));
return!isFailed;
} catch(Exception ex){
return false;
} finally {
closeConnection();
}
}


private boolean isSuccess(List< Match> objPattern,String strCommandPattern){
try {
boolean isFailed = checkResult (expect.expect(objPattern));

if(!isFailed){
expect.send(strCommandPattern);
expect.send(\ r);
返回true;
}
返回false;
} catch(MalformedPatternException ex){
return false;
} catch(Exception ex){
return false;
}
}

private boolean checkResult(int intRetVal){
if(intRetVal == SSHConstants.COMMAND_EXECUTION_SUCCESS_OPCODE){
return true;
}
返回false;
}

public static final int COMMAND_EXECUTION_SUCCESS_OPCODE = -2;
public static final String BACKSLASH_R =\ r;
public static final String BACKSLASH_N =\ n;
public static final String COLON_CHAR =:;
public static String ENTER_CHARACTER = BACKSLASH_R;
public static final int SSH_PORT = 22;
public static String [] linuxPromptRegEx = new String [] {〜]#,〜#,#,:〜#,/ $,}


For some reason,I need to connect to a firewall(based on Linux) and add some rules with Java.

After searching with google for a while, I found that jsch is my best choice.But when I

use it to execute a command,"show hostname" for example, error is returned.If I

execute commands like "ls -l" and "whoami",the results are ok.That's to say,I can only

connect to the Bash Shell! My question is how can I connect to the firewall shell?

My test code as follows:

import java.io.InputStream;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

public class SSHDemo {
    public static void main(String[] args) {
        SSHDemo t = new SSHDemo();
        try {
            t.go();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void go() throws Exception {
        String host = "10.4.44.192";
        String user = "root";
        String password = "root";
        int port = 22;
//      int tunnelLocalPort = 9080;
//      String tunnelRemoteHost = "10.4.44.192";
//      int tunnelRemotePort = 8000;
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setPassword(password);
        localUserInfo lui = new localUserInfo();
        session.setUserInfo(lui);
        session.connect();

        ChannelExec channel = (ChannelExec)session.openChannel("exec");
        channel.setInputStream(null);

            //Pay attension to this line
        channel.setCommand("show hostname");
        channel.setErrStream(System.err);
        channel.connect();
        InputStream in=channel.getInputStream();
        int i=0;
        byte[] tmp=new byte[1024*1024];
        while ((i = in.read(tmp, 0, tmp.length)) != -1) {
            System.out.write(tmp, 0, i);
        }
        in.close();


        channel.disconnect();
        session.disconnect();
        // session.setPortForwardingL(tunnelLocalPort,tunnelRemoteHost,tunnelRemotePort);
        System.out.println("Connected");

    }


    class localUserInfo implements UserInfo {
        String passwd;

        public String getPassword() {
            return passwd;
        }

        public boolean promptYesNo(String str) {
            return true;
        }

        public String getPassphrase() {
            return null;
        }

        public boolean promptPassphrase(String message) {
            return true;
        }

        public boolean promptPassword(String message) {
            return true;
        }

        public void showMessage(String message) {
        }
    }
}

解决方案

Try using ChannelShell by opening shell rather then exec.

Following is small code sample for log in and executing file fro remote java class.

private Expect4j SSH(String hostname, String username,String password, int port) throws Exception {
    JSch jsch = new JSch();
    Session session = jsch.getSession(username, hostname, port);
    if (password != null) {         
        session.setPassword(password);
    }
    Hashtable<String,String> config = new Hashtable<String,String>();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    session.connect(60000);
    channel = (ChannelShell) session.openChannel("shell");
    Expect4j expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());
    channel.connect();      
    return expect;
}

This method will open up SSH stream to remote server which will be used by expect4j for sending commands.

private boolean executeCommands() {
        boolean isSuccess = true;
        Closure closure = new Closure() {
            public void run(ExpectState expectState) throws Exception {
                buffer.append(expectState.getBuffer());//buffer is string buffer for appending output of executed command             
                expectState.exp_continue();
            }
        };
        List<Match> lstPattern =  new ArrayList<Match>();
        String[] regEx = SSHConstants.linuxPromptRegEx;  
        if (regEx != null && regEx.length > 0) {
            synchronized (regEx) {
                for (String regexElement : regEx) {//list of regx like,  :>, /> etc. it is possible command prompts of your remote machine
                    try {
                        RegExpMatch mat = new RegExpMatch(regexElement, closure);
                        lstPattern.add(mat);                        
                    } catch (MalformedPatternException e) {                     
                        return false;
                    } catch(Exception e) {                      
                        return false;
                    }
                }
                lstPattern.add(new EofMatch( new Closure() { // should cause entire page to be collected
                    public void run(ExpectState state) {
                    }
                }));
                lstPattern.add(new TimeoutMatch(defaultTimeOut, new Closure() {
                    public void run(ExpectState state) {
                    }
                }));
            }
        }
        try {
            Expect4j expect = SSH(objConfig.getHostAddress(), objConfig.getUserName(), objConfig.getPassword(), SSHConstants.SSH_PORT);
            expect.setDefaultTimeout(defaultTimeOut);       
            if(isSuccess) {
                for(String strCmd : lstCmds)
                    isSuccess = isSuccess(lstPattern,strCmd);
            }
            boolean isFailed = checkResult(expect.expect(lstPattern));
            return !isFailed;
        } catch (Exception ex) {            
            return false;
        } finally {
            closeConnection();
        }
    }


private boolean isSuccess(List<Match> objPattern,String strCommandPattern) {
        try {   
            boolean isFailed = checkResult(expect.expect(objPattern));

            if (!isFailed) {
                expect.send(strCommandPattern);         
                expect.send("\r");              
                return true;
            } 
            return false;
        } catch (MalformedPatternException ex) {    
            return false;
        } catch (Exception ex) {
            return false;
        }
} 

 private boolean checkResult(int intRetVal) {
    if (intRetVal == SSHConstants.COMMAND_EXECUTION_SUCCESS_OPCODE) {
        return true;
    }
    return false;
 }

    public static final int COMMAND_EXECUTION_SUCCESS_OPCODE = -2; 
public static final String BACKSLASH_R = "\r";
public static final String BACKSLASH_N = "\n";
public static final String COLON_CHAR = ":";
public static String ENTER_CHARACTER = BACKSLASH_R;
public static final int SSH_PORT = 22;  
public static String[] linuxPromptRegEx = new String[]{"~]#","~#","#",":~#","/$",}  

这篇关于如何使用java与防火墙(路由器)建立ssh连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆