SSH服務連線

上善若水~小輝發表於2021-02-09

SSH基本概述

SSH是一個安全協議,在進行資料傳輸時,會對資料包進行加密處理,加密後在進行資料傳輸。確保了資料傳輸安全。

SSH服務

ssh: secure shell, protocol, 22/tcp, 安全的遠端登入

具體的軟體實現:

OpenSSH: ssh協議的開源實現,CentOS預設安裝

SSH協議版本

v1: 基於CRC-32做MAC,不安全;man-in-middle

v2:雙方主機協議選擇安全的MAC方式

基於DH演算法做金鑰交換,基於RSA或DSA實現身份認證

兩種方式的使用者登入認證:

基於password

基於key

ssh選項:

-A:開啟認證代理連線轉發功能;
-a:關閉認證代理連線轉發功能;
-b:使用本機指定地址作為對應連線的源ip地址;
-C:請求壓縮所有資料;
-F:指定ssh指令的配置檔案;
-f:後臺執行ssh指令;
-g:允許遠端主機連線主機的轉發埠;
-i:指定身份檔案;
-l:指定連線遠端伺服器登入使用者名稱;
-N:不執行遠端指令;
-o:指定配置選項;
-p:指定遠端伺服器上的埠;
-q:靜默模式;
-X:開啟X11轉發功能;
-x:關閉X11轉發功能;
-y:開啟信任X11轉發功能。

SSH服務主要功能:

  1. 提供遠端連線伺服器的服務

  2. 對傳輸的資料進行加密

SSHTelnet的區別:

  • ssh服務對傳輸資料進行加密,監聽在本地22/tcp埠, ssh服務預設支援root使用者登入

  • telnet服務不對資料進行加密,監聽在本地23/tcp埠,,Telnet預設不支援root使用者登入

  • 服務連線方式服務資料傳輸服務監聽埠服務登陸使用者
    ssh 加密 22/tcp 預設支援root使用者登陸
    telnet 明文 23/tcp 不支援root使用者登陸
  • 企業面試題

    下列服務,分別使用的那個埠?

     ftp     21/tcp
     dns     53/udp
     ssh     22/tcp
     telnet  23/tcp
     mysql   3306/tcp
     http    80/tcp
     https   443/tcp 443/udp

    使用wireshark驗證telnet明文傳輸與ssh加密傳輸

    1. 安裝telnet服務並執行

     [root@m01 ~]# yum -y install telnet-server
     [root@m01 ~]# systemctl start telnet.socket
    1. 使用wireshark檢測vmnet8網路卡上telnet的流量

    2.  

      3. telnet無法使用root使用者登入Linux系統,需要建立普通使用者       

    3. [root@nfs ~]# useradd admin
      [root@nfs ~]# echo "123"| passwd --stdin admin
      

        使用普通使用者進行telnet登入

    4.  

       搜尋wireshark包含telnet相關的流量

    5.  

       

      6.使用wireshark分析ssh流量

    6.  

       

       

      SSH相關命令

      SSH有客戶端與服務端,我們將這種模式稱為C/S架構,ssh客戶端支援Windows、Linux、Mac等平臺。 在ssh客戶端中包含 ssh|slogin遠端登陸、scp遠端拷貝、sftp遠端資料傳輸、ssh-copy-id祕鑰分發等應用程式。 

    7. SSH有客戶端與服務端,我們將這種模式稱為C/S架構,ssh客戶端支援Windows、Linux、Mac等平臺。 在ssh客戶端中包含 ssh|slogin遠端登陸、scp遠端拷貝、sftp遠端資料傳輸、ssh-copy-id祕鑰分發等應用程式。
    8. ssh遠端登入伺服器命令示例

       ssh [-p port] [user@]hostname [command]
       # -p指定連線遠端主機埠,預設22埠可省略
       # "@"前面為使用者名稱,如果用當前使用者連線,可以不指定使用者
       # "@"後面為要連線的伺服器的IP
       [root@m01 ~]# ssh -p22 root@10.0.0.41  # 遠端登入伺服器
       [root@m01 ~]# ssh root@172.16.1.41 "hostname -i" # 遠端在指定伺服器執行命令
       172.16.1.41

      scp遠端拷貝(全量複製)至遠端主機命令示例

    9. scp [-pr] [-P port] [-l limit] [[user@]host1:]file1 ... [[user@]host2:]file2
      # -P 指定埠,預設22埠可不寫
      # -r 表示遞迴拷貝目錄
      # -p 表示在拷貝檔案前後保持檔案或目錄屬性不變
      # -l 限制傳輸使用頻寬(預設kb)

    10. # 推:將本地/tmp/oldboy推送至遠端伺服器10.0.0.61的/tmp目錄,使用對端的root使用者

      [root@m01 ~]# scp -P22 -rp /tmp/oldboy oldboy@10.0.0.61:/tmp
    11. # 拉:將遠端10.0.0.61伺服器/tmp/oldboy檔案拉取到本地/opt/目錄下

      [root@m01 ~]# scp -P22 -rp root@10.0.0.61:/tmp/oldboy /opt/
    12. # 限速

      [root@m01 ~]# scp /opt/1.txt root@172.16.1.31:/tmp
      root@172.16.1.31 password: 
      test 100% 656MB '83.9MB/s' 00:07 
      # 限速為8096kb,換算為MB,要除以 8096/8=1024KB=1MB
      [root@m01 ~]# scp -rp -l 8096 /opt/1.txt root@172.16.1.31:/tmp
      root@172.16.1.31s password: 
      test 7% 48MB '1.0MB/s' 09:45
    13. 結論:

      1. scp通過ssh協議加密方式進行檔案或目錄拷貝。

      2. scp使用連線時指定的使用者作為為拷貝檔案或目錄的許可權。

      3. scp支援資料推送和拉取,每次都是全量拷貝,效率較低。

    14. sftp遠端資料傳輸命令

       # 預設可以通過sftp命令連線sftp服務
       sftp root@10.0.0.61
       sftp -oPort=22222 root@10.0.0.61  # -o 使用ssh的選項
       # sftp使用get下載檔案至於本地伺服器
       sftp> get conf.txt /tmp/
       # sftp使用put上傳本地伺服器檔案~至遠端伺服器
       sftp> put /root/t1.txt /root/

      ssh加密通訊

    15. 基於使用者和口令登入驗證 1 客戶端發起ssh請求,伺服器會把自己的公鑰傳送給使用者 2 使用者會根據伺服器發來的公鑰對密碼進行加密 3 加密後的資訊回傳給伺服器,伺服器用自己的私鑰解密,如果密碼正確,則 使用者登入成功

      示例:ssh 192.168.34.100 預設以root身份連線對方的主機

      當我們第一次連線對方的時候,會出現是否想去連線對方的提示資訊,如果選擇yes,並輸入對方的口令後,就會將對方的公鑰檔案存到自己/root/.ssh 目錄下,此目錄下有一個檔名叫konwn_hosts

    16. SSH驗證方式

      基於賬戶密碼遠端登入

      知道伺服器的IP埠,賬號密碼,即可通過ssh客戶端命令登陸遠端主機。

      ~ ssh -p22 root@10.0.0.61
       root@10.0.0.61 password:
       [root@m01 ~]#

      基於祕鑰遠端登入

      預設情況下,通過ssh客戶端命令登陸遠端伺服器,需要提供遠端系統上的帳號與密碼,但為了降低密碼洩露的機率和提高登陸的方便性,建議使用金鑰驗證方式。

       

       

       

      1. 在伺服器上生成非對稱金鑰,使用-t指定要建立的金鑰型別, 使用-C提供新註釋

       [root@m01 ~]# ssh-keygen -t rsa -C 593528156@qq.com
       # 預設一路回車即可
      1. 將A伺服器上的公鑰推送至B伺服器

       ssh-copy-id [-i [identity_file]] [user@]hostname
       -i        # 指定下發的公鑰檔案的路徑
       [user@]   # 指定分發公鑰的使用者身份,預設以當前系統使用者身份
       hostname  # 下發公鑰至那臺伺服器, 填寫遠端主機IP地址
       # 分發公鑰,[將A伺服器的公鑰寫入B伺服器的~/.ssh/authorized_keys檔案中]
       [root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.41
      1. 如果A伺服器連線B伺服器無需密碼則表示祕鑰已配置成功

       [root@m01 ~]# ssh root@172.16.1.41
       [root@nfs ~]#

      SSH應用場景

      使用者通過Windows/MAC/Linux客戶端連線跳板機免密碼登入,跳板機連線後端無外網的Linux主機實現免密登入,架構圖如下。 實踐多使用者登陸一臺伺服器無密碼 實踐單使用者登陸多臺伺服器免密碼

    17.  

      1. windows客戶端使用Xshell生成祕鑰對,並下發公鑰至跳板機

                   1) Xshell-->選擇工具-->新建使用者金鑰生成嚮導

    18.  

       

       

       2) 選擇建立金鑰型別和金鑰長度,預設即可,選擇下一步

    19.  

      3) 生成公鑰對,選擇下一步 

    20.  

       4) 填寫祕鑰名稱。祕鑰加密密碼不建議配置

    21.  

       5) Windows會提示密碼為空,選是即可

    22.  

      6) 生成祕鑰後,點選Xshell-->工具-->使用者祕鑰管理者 

    23.  

      7) 選擇對應祕鑰的屬性 

    24.  

       8) 選擇對應祕鑰的公鑰,將其複製或者儲存為檔案

    25. 9) 將從WIndows下複製好的公鑰貼上至跳板機~/.ssh/authorized_keys中,然後測試

       [root@m01 ~]# cd ; umask 077; mkdir -p .ssh ;cd .ssh
       [root@m01 .ssh]# vim authorized_keys  # 新增windows公鑰
      1. 跳板機下發公鑰至後端主機

      1) 在跳板機上生成祕鑰對

       [root@m01 ~]# ssh-keygen -t rsa -C manager@qq.com

      2) 拷貝跳板機上的金鑰至後端主機,如果SSH不是使用預設22埠, 使用-p指定對應埠

       [root@m01 ~]# ssh-copy-id  -i /root/.ssh/id_rsa.pub -p22 root@172.16.1.31
       [root@m01 ~]# ssh-copy-id  -i /root/.ssh/id_rsa.pub -p22 root@172.16.1.41

      3) 在m01管理機上測試是否成功登陸兩臺伺服器

    26. [root@m01 ~]# ssh root@172.16.1.41
      [root@nfs01 ~]# exit
      [root@m01 ~]# ssh root@1172.16.1.31
      [root@backup ~]# exit
    27. 通過跳板機能實現scp拷貝檔案免密碼
    28. [root@m01 ~]# scp zls.txt root@172.16.1.31:/tmp
      zls.txt 100% 0 0.0KB/s 00:00 
      [root@m01 ~]# scp zls.txt root@172.16.1.41:/tmp
      zls.txt 100% 0 0.0KB/s 00:00
    29. 通過跳板機獲取所有機器的load,CPU,Memory等資訊(思考:如果伺服器數量多,如何併發檢視和分發資料)
    30. [root@m01 ~]# cat all.sh 
      #!/usr/bin/bash
      [ $# -ne 1 ] && echo "請輸入執行的命令" && exit 1
      
      for i in 31 41
      do
      echo "172.16.1.$i"
      ssh root@172.16.1.$i "$1"
      done
    31. #!/bin/bash
      #jumpserver
      lb01=10.0.0.5
      lb02=10.0.0.6
      web01=10.0.0.7
      web02=10.0.0.8
      web03=10.0.0.9
      nfs=10.0.0.31
      backup=10.0.0.41
      db01=10.0.0.51
      m01=10.0.0.61
      zabbix=10.0.0.71
      
      menu(){
      cat <<-EOF
      +-------------------------+
      | 1) lb01 |
      | 2) lb02 |
      | 3) web01 |
      | 4) web02 |
      | 5) web03 |
      | 6) nfs |
      | 7) backup |
      | 8) db01 |
      | 9) m01 |
      | 10) zabbix |
      | h) help |
      +-------------------------+
      EOF
      }
      #選單函式
      menu
      
      #連線函式
      connect(){
      ping -c 1 -w 1 $1 &>/dev/null
      if [ $? -eq 0 ];then
      ssh root@$1
      else
      echo -e "\033[5;4;40;31m 別連了,我的哥,$2:$1機器都沒開!!!\033[0m"
      fi
      }
      
      #控制不讓輸入ctrl+c,z
      trap "" HUP INT TSTP
      while true
      do
      read -p "請輸入要連線的主機編號:" num
      case $num in
      1|lb01)
      connect $lb01 lb01
      ;;
      2|lb02)
      connect $lb02 lb02
      ;;
      3|web01)
      connect $web01 web01
      ;;
      4|web02)
      connect $web02 web02
      ;;
      5|web03)
      connect $web03 web03
      ;;
      6|nfs)
      connect $nfs nfs
      ;;
      7|backup)
      connect $backup backup
      ;;
      8|db01)
      connect $db01 db01
      ;;
      9|m01)
      connect $m01 m01
      ;;
      10|zabbix)
      connect $zabbix zabbix
      ;;
      h|help)
      clear
      menu
      ;;
      close)
      break
      ;;
      esac
      done
    32. 指令碼實現(圖形化跳板機)
    33. #!/bin/bash
      
      lb01=10.0.0.5
      lb02=10.0.0.6
      web01=10.0.0.7
      web02=10.0.0.8
      web03=10.0.0.9
      nfs=10.0.0.31
      backup=10.0.0.41
      db01=10.0.0.51
      db02=10.0.0.52
      m01=10.0.0.61
      zabbix=10.0.0.71
      
      title="歡迎進入lnb跳板機-$m01"
      
      #跳板機函式
      JUMP(){
      OPTION=$(whiptail --title "$title" --menu "請選擇你要連線的伺服器:" 25 60 11 \
      "1" "連線 lb01" \
      "2" "連線 lb02" \
      "3" "連線 web01" \
      "4" "連線 web02" \
      "5" "連線 web03" \
      "6" "連線 nfs" \
      "7" "連線 backup" \
      "8" "連線 db01" \
      "9" "連線 db02" \
      "10" "連線 m01" \
      "11" "連線 zabbix" 3>&1 1>&2 2>&3)
      
      exitstatus=$?
      if [ $exitstatus = 0 ]; then
      case $OPTION in
      1)
      connect $lb01
      ;;
      2)
      connect $lb02
      ;;
      3)
      connect $web01
      ;;
      4)
      connect $web02
      ;;
      5)
      connect $web03
      ;;
      6)
      connect $nfs
      ;;
      7)
      connect $backup
      ;;
      8)
      connect $db01
      ;;
      9)
      connect $db02
      ;;
      10)
      connect $m01
      ;;
      11)
      connect $zabbix
      ;;
      12)
      connect $te
      ;;
      13)
      connect $te_web
      ;;
      esac
      fi
      }
      
      #主機函式
      HOST_INFO (){
      HOST=$(whiptail --title "$title" --checklist \
      "請選擇要傳送的主機名:" 25 60 11 \
      "$lb01" "傳送給lb01" OFF \
      "$lb02" "傳送給lb01" OFF \
      "$web01" "傳送給web01" OFF \
      "$web02" "傳送給web02" OFF \
      "$web03" "傳送給web03" OFF \
      "$nfs" "傳送給nfs" OFF \
      "$backup" "傳送給backup" OFF \
      "$db01" "傳送給db01" OFF \
      "$db02" "傳送給db02" OFF \
      "$m01" "傳送給m01" OFF \
      "$zabbix" "傳送給zabbix" OFF 3>&1 1>&2 2>&3)
      }
      
      SER_INFO(){
      SER=$(whiptail --title "$title" --checklist \
      "請選擇要檢查的服務:" 25 60 10 \
      "nginx" "檢查nginx" OFF \
      "mysqld" "檢查mysqld" OFF \
      "php" "檢查php" OFF \
      "tomcat" "檢查tomcat" OFF \
      "sshd" "檢查sshd" OFF \
      "httpd" "檢查httpd" OFF \
      "vsftpd" "檢查vsftpd" OFF \
      "docker" "檢查docker" OFF \
      "saltstack" "檢查saltstack" OFF \
      "rsyncd" "檢查rsyncd" OFF 3>&1 1>&2 2>&3)
      }
      
      #連線函式
      connect(){
      whiptail --title "$title" --yesno "你確定要連線這臺機器麼?想好了啊!!!" 10 60
      if [ $? -eq 0 ];then
      {
      ping -c 1 -w 1 $1 >/tmp/ping.txt 2>/dev/null
      if [ $? -ne 0 ];then
      for ((i = 0 ; i <= 100 ; i+=30)); do
      sleep 1
      echo $i
      done
      fi
      } | whiptail --gauge "emmmm...我正在連線$1,檢測網路中,等我一哈子..." 6 60 0
      grep 'ttl' /tmp/ping.txt &>/dev/null
      if [ $? -eq 0 ];then
      ssh root@$1
      else
      whiptail --title "$title" --msgbox "網路檢測失敗,別連了,我的哥,$1機器都沒開" 10 60
      fi
      
      fi
      }
      
      #推送檔案函式
      SCP (){
      HOST_INFO
      
      PA=$(whiptail --title "$title" --inputbox "請輸入需要推送的檔案本地路徑:" 10 60 /etc/passwd 3>&1 1>&2 2>&3)
      DEST=$(whiptail --title "$title" --inputbox "請輸入需要分發到主機的哪個目錄:" 10 60 /tmp 3>&1 1>&2 2>&3)
      {
      for H in ${HOST};do
      echo "scp $PA ${H}:${DEST}"|bash &>/dev/null
      for ((i = 0 ; i <= 100 ; i+=50));do
      sleep 1
      echo $i
      done
      done
      } | whiptail --gauge "彆著急,正在傳送中..." 6 60 0
      }
      
      #檢查磁碟函式
      CHECK_DISK (){
      HOST_INFO
      
      for H in ${HOST};do
      echo "ssh $H 'df -h' "|bash > /tmp/disk
      whiptail --title "$(date +%F-%T) | $H 磁碟資訊" --msgbox "$(cat /tmp/disk)" 10 60
      done
      }
      
      #檢查記憶體函式
      CHECK_MEM (){
      HOST_INFO
      
      for H in ${HOST};do
      echo "ssh $H 'free -m' "|bash > /tmp/meminfo
      whiptail --title "$(date +%F-%T) | $H 記憶體資訊" --msgbox "$(cat /tmp/meminfo)" 30 80
      done
      }
      
      #檢視服務狀態
      CHECK_SER (){
      HOST_INFO
      SER_INFO
      
      for H in ${HOST};do
      for S in ${SER};do
      HO=`echo "$H"|awk -F \" '{print $2}'`
      PROC=`ssh $HO "ps -ef|grep $S|wc -l"`
      NUM=$( expr $PROC - 3 )
      if [[ $PROC > 3 ]];then
      whiptail --title "$(date +%F-%T) | $H 服務資訊" --msgbox "${S} 存活 | 程式數:$NUM" 10 60
      else
      whiptail --title "$(date +%F-%T) | $H 服務資訊" --msgbox "${S} 沒有存活| 程式數:$NUM" 10 60
      fi
      done
      done
      }
      
      #批量之心命令函式
      EXEC_CMD(){
      HOST_INFO
      
      CMD=$(whiptail --title "$title" --inputbox "請輸入要執行的命令:" 10 60 ifconfig 3>&1 1>&2 2>&3)
      for H in ${HOST};do
      HO=`echo "$H"|awk -F \" '{print $2}'`
      RES=`ssh $HO "$CMD"`
      whiptail --title "$(date +%F-%T) | $H 命令執行結果" --msgbox "$RES" 40 80
      done
      
      
      }
      
      
      #退出函式
      EXIT(){
      pass=$(whiptail --title "$title" --passwordbox "請輸入你的退出密碼" 10 60 3>&1 1>&2 2>&3)
      if [ $pass == '123456' ];then
      exit
      else
      whiptail --title "$title" --msgbox "密碼錯誤,你不是運維,小樣的~~~" 10 60
      continue
      fi
      }
      
      whiptail --title "$title" --msgbox "lnb跳板機,給你全新不一樣的feel,進去了,就不想出來" 10 60
      
      #抓取鍵盤訊號
      trap "" HUP INT TSTP
      while true;do
      OPTION=$(whiptail --title "$title" --menu "請選擇你的動作(輕點...)" 15 60 8 \
      "1" "SSH遠端連線" \
      "2" "推送檔案" \
      "3" "檢視磁碟空間" \
      "4" "檢視記憶體空間" \
      "5" "檢視服務狀態" \
      "6" "批量執行命令" \
      "7" "輕鬆一下(game)" \
      "8" "退出" 3>&1 1>&2 2>&3)
      
      exitstatus=$?
      if [ $exitstatus = 0 ]; then
      case $OPTION in
      1)
      JUMP
      ;;
      2)
      SCP
      ;;
      3)
      CHECK_DISK
      ;;
      4)
      CHECK_MEM
      ;;
      5)
      CHECK_SER
      ;;
      6)
      EXEC_CMD
      ;;
      7)
      sh /root/eluosi.sh
      ;;
      8)
      EXIT
      ;;
      esac
      fi
      done
    34. vim ip.sh 書寫指令碼檔案
      #!/bin/bash
      user=wang
      password=centos
      ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
      
      while read ip ;do
      expect <<EOF
      set timeout 10
      spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $user@$ip
      expect {
      "yes/no" { send "yes\n";exp_continue }
      "password" { send "$password\n" }
      }
      expect eof
      EOF
      done < ip list.txt
      
      SSH安全優化
      SSH作為遠端連線服務,通常我們需要考慮到該服務的安全,所以需要對該服務進行安全方面的配置。
      
      更改遠端連線登陸的埠
      
      禁止ROOT管理員直接登入
      
      密碼認證方式改為金鑰認證
      
      重要服務不使用公網IP地址
      
      使用防火牆限制來源IP地址
      
      SSH服務登入防護需進行如下配置調整,先對如下引數進行了解
      Port 6666 # 變更SSH服務遠端連線埠
      PermitRootLogin no # 禁止root使用者直接遠端登入
      PasswordAuthentication no # 禁止使用密碼直接遠端登入
      UseDNS no # 禁止ssh進行dns反向解析,影響ssh連線效率引數
      GSSAPIAuthentication no # 禁止GSS認證,減少連線時產生的延遲
      
      #END#
      免互動expect[擴充套件]
      安裝expect
      
       [root@m01 ~]# yum install  expect  -y
      編寫expect指令碼
      
       #!/usr/bin/expect
       set ip 10.0.0.51
       set pass 123456
       set timeout 30
       spawn ssh root@$ip
       expect {
               "(yes/no)" {send "yes\r"; exp_continue}
               "password:" {send "$pass\r"}
       }
       expect "root@"  {send "df -h\r"}
       expect "root@"  {send "exit\r"}
       expect eof
      免互動sshpass[擴充套件]
      安裝sshpass
      
       [root@m01 ~]# yum install sshpass  -y
      使用sshpass命令
      
       [root@m01 ~]# sshpass -p 123456 ssh root@10.0.0.51
       ​
       [option]
       -p:指定密碼
       -f:從檔案中取密碼
       -e:從環境變數中取密碼
       -P:設定密碼提示
      使用使用者名稱密碼驗證方式
      
      ssh遠端連線的方式:
      
      172.16.1.41連線172.16.1.31
      
       1 直接連線
       ssh  10.0.0.31
       2 指定使用者連線
       ssh root@10.0.0.31    linux
       ssh root@10.0.0.31     windows
       3 指定使用者加埠方式
       ssh  -p22   root@10.0.0.31   linux
       ssh root@10.0.0.31   22
      1. 實驗一:

        安裝telnet軟體:進行跳板機實驗(SSH埠本地轉發功能)

        centos6 開啟telnet功能:

        yum install telnet-server 安裝telnet
        
        chkconfig telnet on 開啟telnet功能
        
        service xinetd start 開啟xinetd功能

        centos7:開啟telnet功能

        yum instlal telnet-server
        
        systemctl start telnet.socket

        模擬情況:

        C:模擬telnet服務端

        B:模擬ssh服務端

        A:模擬客戶端

        telnet服務端拒絕客戶端的訪問:C拒絕A訪問

        流程解釋:

        資料一旦被telnet開啟以後,資料會傳送到本機9527埠,再在本機開一個隨機埠,充當ssh客戶端,再把資料流量傳送到22埠的ssh服務端,收到資料以後,解密資料,臨時開一個隨機埠充當客戶端,再把流量傳送到23埠telnet服務端

      2.  

         

        1)在telnet服務端執行防火牆阻擋功能,阻擋客戶端訪問:C拒絕A

        iptables -A INPUT -s 192.168.34.101 -j REJECT

        2)我們要檢視自己和服務端哪些埠未被佔用,在A主機找一個未用的埠進行繫結,此時,9527埠未被使用:

      3. 第一種連線方式:

        [root@centos7~]#ssh -L 9527:192.168.34.100:23 -Nf 192.168.34.200 在A執行此命令,開啟B主機上未被佔用的埠9527,然後A通過此9527埠連線B伺服器最後再到telnet端。-f 是後臺執行,不加-f就會前臺執行。
        
        [root@centos7~]#telnet 127.0.0.1 9527 在A上執行telnet連線操作,並輸入指定的9527埠號
        Trying 127.0.0.1...
        Connected to 127.0.0.1.
        Escape character is '^]'.
        CentOS release 6.10 (Final)
        Kernel 2.6.32-754.el6.x86_64 on an x86_64
        centos6.10.localdomain login: 使用者名稱
        Password: 密碼
        Last login: Thu Oct 24 20:56:12 from 192.168.34.200 #以顯示連線到C伺服器的機器是B,但實際是從A主機將9527埠轉發連線到C伺服器
        [liu@centos6~]$
      4.  第二種連線方式:

      5.  ssh -L 9527:192.168.34.100:23 -fNg 192.168.34.200 在A機器上開啟B機器的9527埠,在B機器搭上隧道。
        telnet 192.168.34.101 9527 在A機器上通過埠9527,連線C機器
      6. 在C機器上檢視當前連線的資訊:
      7. [root@centos6~]#ss -nt
        State Recv-Q Send-Q Local Address:Port Peer Address:Port
        ESTAB 0 52 192.168.34.100:22 192.168.34.1:49369
        ESTAB 0 0 192.168.34.100:23 192.168.34.200:53668 (其中100:23位telnet伺服器端IP和23埠,200:53668為ssh服務端的IP和隨機埠)
      8. 結論:當客戶端開啟9527埠,請求到ssh協議封裝將資料包文傳送給ssh伺服器端,然後在ssh伺服器端上解封裝,開啟隨機埠將資料包文傳給telnet伺服器,telnet伺服器最終得到資料,實現客戶端連線telnet伺服器端。

        注意:雖然能通過跳板機連線到telnet伺服器,但是外部機器連線內部機器時,一般防火牆不會開啟22埠,客戶端無法到達服務端,最終無法連線telnet端的服務。

         遠端轉發: -R sshserverport:remotehost:remotehostport sshserver

      9. 示例: ssh -R 9527:telnetsrv:23 -Nf sshsrv 讓sshsrv偵聽9527埠的訪問,如有訪問,就加密後通過ssh服務轉發請求到本 機ssh客戶端,再由本機解密後轉發到telnetsrv:23

      10. Data<--> sshsrv:9527 <--> sshsrv:22 <--> localhost:XXXXX <--> localhost:YYYYY<-->telnetsrv:23

        一般防火牆從外部到內部會阻止訪問,但從內部到外部不會阻止訪問:

        遠端轉發實驗:

        三臺機器:C:伺服器,B:跳板機(ssh伺服器),A:客戶端

        C伺服器只允許telnet連線(23埠)訪問,不允許外部客戶端直接訪問,B跳板機是一個ssh伺服器;有一個使用者需要從外部連線到企業內部的C伺服器。

        模擬:C 不允許A訪問:

        當前模擬telnet服務端阻擋服務端訪問:

        在C執行防火牆阻擋A:

        iptables -A INPUT -s 192.168.34.101 -j REJECT
        [root@b~]#ssh -R 9527:192.168.34.100:23 -Nf 192.168.34.101 #在B機器上後臺開啟A主機的9527埠
        root@192.168.34.101's password: #輸入本機密碼驗證
        [root@b~]#
        [root@centos7~]#telnet 127.0.0.1 9527 #在A機器上用telnet連線本地IP地址和9527埠,可以遠端訪問到內部C伺服器
        Trying 127.0.0.1...
        Connected to 127.0.0.1.
        Escape character is '^]'.
        CentOS release 6.10 (Final)
        Kernel 2.6.32-754.el6.x86_64 on an x86_64
        centos6.10.localdomain login: wang
        Password:
        Last login: Sun Oct 27 11:42:33 from 192.168.34.200 #此時已經連線到C主機,並顯示連線C主機是從跳板機B連線的。
        [wang@centos6~]$
      11. 總結:客戶端開啟9527埠走ssh協議將資料包文封裝,傳送到跳板機,跳板機解封裝報文得到資料,跳板機開啟一個隨機埠,傳送資料包文到telnet服務端,實現外部的客戶機通過內部跳板機連線到telnet伺服器。

        注意:防火牆只會阻擋從外部到內部的埠連線,不會阻擋從內部到外部的埠,現實生產中比較實用,省去了重新設定防火牆的時間。

      12. 另一種遠端埠轉發情況:外部有一個客戶端(A)連線外部的服務端(B),然後再通過服務端連線內部的跳板機(ssh伺服器C),最後到達telnet服務端(D),此處可以將外部客戶端和服務端作為

        一個堡壘機,內部的ssh伺服器和telnet伺服器可以看做是一個堡壘機,具體連線情況如下:

        1)需要將外部客戶端(A)的ssh配置檔案開啟:

        vim /etc/ssh/sshd_config
        修改裡邊的檔案gateway no 改為yes,然後重啟ssh服務,systemctl restart sshd
        2)ssh -R 9527:192.168.34.100:23 -fNg 192.168.34.101 ssh伺服器端(C)輸入當前的命令,將A客戶端的9527埠開啟,開啟後臺隧道。
        3)telnet 192.168.34.101 9527 在外部客戶端(A)輸入自己的本地IP也可以連線到telnet服務端(D)。

        SSH動態埠轉發:(合理上國外網站)

        客戶端---->代理伺服器----->國外網站

        模擬:

        A: 本地機器

        B: 代理客戶端

        C: 外國網路

        當用firefox訪問internet時,本機的9527埠做為代理伺服器,firefox的訪問請求被轉發到sshserver上,由sshserver替之訪問internet

      13.  

         

        以下為搭建A訪問C的過程:

        實現Linux主機通過代理進行訪問國外網站:

         iptables -A  INPUT -s 192.168.34.101 -j REJECT   設定C阻擋A模擬。
          echo www.google.com > /var/www/html/index.html  在C建立google網站,訪問此google網站實驗
          service httpd start  啟動C的httpd服務
          ssh -D 9528 192.168.34.200 -fN   在A機器搭建代理客戶端的後臺隧道
         curl --socks5 127.0.0.1:9528 192.168.34.100   在A上輸入此命令,訪問外國網站即可  www.google.com

        通過代理可以訪問windows版國外網站搭建:

      14. [root@b.ssh]#iptables -A INPUT -s 192.168.34.1 -j REJECT C主機進行防火牆控制windows視窗連線
        [root@centos7~]#ssh -D 9528 192.168.34.200 -fNg -g選項自己能通過閘道器訪問windows網站,別人也可以訪問自己
        [root@centos7~]#curl --socks5 127.0.0.1:9528 192.168.34.100 也可以通過輸入命令訪問windows國外網站
        www.google.com
      15. 在windows網頁上高階設定也可以在客戶端上訪問外國網路:
      16.  

         

         

         

         伺服器端:sshd, 配置檔案: /etc/ssh/sshd_config 常用引數:

      17. Port 埠號
        ListenAddress ip 監聽IP地址
        LoginGraceTime 2m 等待時間是2分鐘
        PermitRootLogin yes 禁止ROOT使用者模式進行ssh連線
        StrictModes yes 檢查.ssh/檔案的所有者,許可權等
        MaxAuthTries 6 錯誤的連線最大次數,預設是3次
        MaxSessions 10 同一個連線最大會話
        PubkeyAuthentication yes 支援公鑰驗證
        PermitEmptyPasswords no 禁止空口令登陸
        PasswordAuthentication yes 支援口令驗證
        GSSAPIAuthentication yes 預設是yes,建議改為no影響連線速度。
        UsePAM yes # 使用PAM模組
        ClientAliveInterval 2 檢查客戶端是否活躍,每兩秒檢查一次,客戶端10s時間不動就會斷開
        ClientAliveCountMax 3 連續檢查3次客戶端活躍情況。
        GatewayPorts no 閘道器介面預設值是no
        ClientAliveInterval 單位:秒
        ClientAliveCountMax 預設3
        UseDNS yes # 反向解析SSH,需要將此改為no,SSH連線與資料傳輸就會變快。
        GSSAPIAuthentication yes 提高速度可改為no
        MaxStartups 未認證連線最大值,預設值10, 連線併發連線數,當到達20,開始拒絕部分人。
        Banner /path/file 登陸提示檔案
      18. 限制可登入使用者的辦法: AllowUsers user1 user2 user3 白名單使用者 DenyUsers 黑名單使用者 加入名單的使用者名稱就無法通過ssh連線 AllowGroups DenyGroups

        結論:白名單優先順序比黑名單優先順序高,如果黑白名單同時有一個IP地址被禁止ssh連線,預設可以連線。

        /etc/ssh/sshd_config配置檔案部分內容詳解:

        伺服器端修改配置檔案中以下兩項進行修改,可以加速ssh的連線

      19. vim /etc/ssh/sshd_conf
        UseDNS no 
        GSSAPIAuthentication no
        • 在/etc/ssh/sshd_config配置中,我們預設的port(埠號)是22,可以通過此配置檔案將自己的埠號改掉,以防黑客暴力破解當前的使用者賬號和密碼,修改完之後service sshd restart。

        修改完之後的埠號,我們再連線時需要指定埠號:ssh 192.168.34.100 -p 44(修改後的埠號)

      • 我們可以在指定的配置檔案中輸入要監聽的IP地址:listenadress 192.168.34.10 直接繫結自己的IP地址和埠號,預設只能自己通過ssh連線。

    35.  

       還可以在最後一行限制普通使用者登入情況,例如:allowusers wang 只能wang使用者進行ssh登入。

    36.  

      ssh服務的最佳實踐

      • 建議使用非預設埠

      • 禁止使用protocol version 1

      • 限制可登入使用者

      • 設定空閒會話超時時長

      • 利用防火牆設定ssh訪問策略

      • 僅監聽特定的IP地址

      • 基於口令認證時,使用強密碼策略

      • 使用基於金鑰的認證

      • 禁止使用空密碼

      • 禁止root使用者直接登入

      • 限制ssh的訪問頻度和併發線上數

      • 經常分析日誌

      SSH服務配置檔案
      /etc/ssh/sshd_config

      Port 22 --- 修改服務埠資訊
      ListenAddress 0.0.0.0 --- 監聽地址 指定一塊網路卡能夠接受遠端訪問請求 *****
      PS: 指定監聽地址只能是本地網路卡上有的地址
      PermitEmptyPasswords no --- 是否允許遠端使用者使用空密碼登入,預設不允許
      PermitRootLogin yes --- 是否禁止root使用者遠端連線主機 建議改為no
      GSSAPIAuthentication no --- 是否開啟GSSAPI認證功能 不用的時候關閉 
      UseDNS no --- 是否開啟反向DNS解析功能 建議進行關閉

      ssh故障告警

      ssh WARNING:REMOTE HOST IDENTIFICATION HAS CHANGED(警告:遠端主機標識已更改)

      ssh 192.168.1.88 出現以下警告:
      
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
      Someone could be eavesdropping on you right now (man-in-the-middle attack)!
      It is also possible that a host key has just been changed.
      The fingerprint for the ECDSA key sent by the remote host is
      SHA256:Rf81ie6kn6C04O3fJKR3YyJ1ApVmIxwTo8zhZ+sbsjY.
      Please contact your system administrator.
      Add correct host key in /root/.ssh/known_hosts to get rid of this message.
      Offending ECDSA key in /root/.ssh/known_hosts:4
      ECDSA host key for 192.168.1.88 has changed and you have requested strict checking.
      Host key verification failed.
      
      解決方案: 刪除 /root/.ssh/known_hosts 檔案中對應IP的那一行即可
      不用互動輸入密碼資訊,進行遠端連線分發公鑰:
      第一步驟: 下載安裝軟體
      yum install -y sshpass
      
      第二步驟: 執行免互動方式分發公鑰命令
      sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.41
      
      如何不要輸入連線yes或no的確認資訊
      ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.41 "-o StrictHostKeyChecking=no"
      
      服務埠號發生變化,如何進行批量分發公鑰
      sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub root@172.16.1.41 -p 52113 "-o StrictHostKeyChecking=no"
      

        

相關文章