How to make a ssh connection to a firewall(router)

2019-03-05 09:01发布

问题:

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) {
        }
    }
}

回答1:

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[]{"~]#","~#","#",":~#","/$",}