顯示具有 TCP/IP 標籤的文章。 顯示所有文章
顯示具有 TCP/IP 標籤的文章。 顯示所有文章

2020年9月4日 星期五

Wireshark 學習筆記 (一) : 在 Win10 安裝

昨天因為工作上關係收到一封含有 .pcap 檔 (Wireshark) 附件的 email, 以前安裝的 Wireshark 因辦公室電腦升版 Win10 重灌消失了, 所以得重新下載安裝. 想學習 Wireshark 醞釀好久了, 趁這個機會先把工具弄好.

目前最新版是 v3.2.6, 但這版安裝時居然抓不到畫面, 只好拿之前安裝 v1.12.8 版的圖片充數, 反正就一直按確定, 中間有要選擇安裝其他選項用預設即可 :

# https://www.wireshark.org/download.html










Wireshark 在 Ubuntu 也可以安裝, 參考 :

# Linux系統安裝wireshark

找時間在我那台 Jetson Nano 上安裝看看.

2016年3月5日 星期六

幾本 TCP/IP 的好書

以下這幾本跟總圖借的書暫時沒時間看要先還, 所以先做個紀錄, 以便將來按圖索驥, 等我回頭玩 Arduino 與 Raspbery Pi 時再借回來研究.

1. TCP/IP嵌入式系統Web伺服器第二版 (全華, 蕭榮修, 總館)


此書相當特別, 專門介紹如何在微控器 (書中採用 PIC) 上實作 TCP/IP 堆疊, 同類書幾乎沒有, 此書僅總館一本.

2. TCP/IP 通訊協定 第四版 (全華, 張承翃譯, 總館, 美濃)
此翻譯書應該是講 TCP/IP 規格最詳細的書, 圖表特多, 最重要的是包含 RTP 與 SCTP 協定, 這在其他書找不到.

3. 從零開始了解 TCP/IP 基礎架構 (佳魁, 楊波, 總館)


這本強國人寫的書以淺顯文字加漫畫向外行或初入門者介紹 TCP/IP, 可以當 做閒書來看.

4. 網路 TCP/IP 教本 修訂版 (全華, 江輔政, 總館)


此書特點是著重在封包的範例分析, 而非規約欄位的解說, 全書有上百個峰包範例, 詳細到擷取的 byte 都展開來解析印證, 是實戰級的好書, 適合理論課上完後來實際操練用.

5. TCP/IP 入門 (全華, 林立國譯, 總館)


這本小巧的日文翻譯書是針對 TCP/IP 入門者而寫,  對於基礎技術解說詳盡, 也是可以當閒書看的技術書籍.

6. TCP/IP最佳入門實用書第七版 (碁峰, 蕭文龍, 總館, 河堤)


能出到第七版表示書寫得好熱銷. 此書以 Wireshark 詳細解說規約格式與運作, 連 state machine 都畫出來. 後面有專章介紹 IPv6 與 MRTG (要安裝 Perl).

7. TCP/IP 協定觀念與實作 第二版 (旗標, 施威銘研究室, 總館, 岡山)


這本書對觀念講得非常細, 書中有許多補充說明. 總館為 93 年版, 岡山分館有 2008 年版.

8. TCP/IP網路通訊協定 第二版 (博碩 2012, 陳祥輝, 河堤)
這本書是我最早借的一本 TCP/IP 書, 特點是程序圖示多且詳細, 例如 TCP 三向交握就有多張流程圖解說.

9. 網路概論第三版 (博碩, 陳湘陽, 河堤)

此書顧名思義範圍較廣, 並非專講 TCP/IP, 還涉及無線網路與 3G/LTE 部分.

10. 電腦網路概論 2013 最新版 (全華, 陳雲龍, 河堤)


本書已出 2015 第五版, 此書可能是要做為教科書, 寫得精簡扼要, 但圖表很詳細, 後面有介紹用 wireshark 抓取信號.

20160930 補充 :

11. 讓網路上的每個封包都無所遁形 :精用Wireshark

Source : 金石堂

這本書是專門討論 Wireshark 應用的好書.



2015年11月18日 星期三

好書 : 兩本 Wirshark 的中文書

最近因為研究 ESP8266 網路連線的關係, 發現自己對網路了解不夠, 加上工作上要用到 TCP/IP 的東西, 所以去市圖借了兩本協定分析軟體 Wireshark 的書, 打算好好地補強這方面的知識. 以往我都專注在應用層面的東西, 對於這些底層的東西興趣缺缺, 例如有一陣子公司鼓勵考證照, 我寧可去考 Java 認證, 也不要去考 CCNA. 總之, 我當時覺得, 路由器設定之類的東西好死板, 讀來味如嚼蠟. 但現在見解不同了, 從終端的手機, 到雲端的伺服器, 通通要用到 TCP/IP, 如果只有皮毛的認識, 恐怕要玩應用也玩不起來.

這兩本都是翻譯書, 第一本譯自 No starch press 的 "Practical Packet Analysis" :

# 碁峰-實戰封包分析 : 使用 Wireshark

Source : 博客來

這本書很受歡迎, 已經是第二版了, 還出現在維基百科的延伸導讀項目下, 參閱 :

# Wiki : Wireshark.

此書的特色如其書名, 強調實戰, 後半部 (8~11 章) 提供各種日常網路管理會遇到的實際案例, 前半部 (1~7 章) 則是介紹網路分析的基礎知識. 書中的範例檔案可在出版社網站下載 :

# http://www.nostarch.com/packet2.htm

第二本書譯自日本人久米原榮與上田浩的著作, 其實這本我兩年前想寫 Java 網路程式時早以前就借過, 但一直沒時間閱讀. 這本書是以主題條列方式編輯, 所以不一定要從頭依序讀到尾, 比較像是手邊可隨時查閱的工具書.

# 博碩-Wireshark 網路協定分析與管理
Source : 博客來

Wireshark 是採用 GNU 授權的免費開源軟體, 其前身是 Ethereal, 由 Gerald Combs 於 1997 年開始研發, 後來吸引許多高手加入開發團隊. 不過當 Gerald Combs 於 2006 年離開 NIS 公司跳槽到另一家公司時, 由於 Ethereal 是 NIS 公司的商標, 所以就改名為 Wireshark 了.


2014年5月2日 星期五

Java 的 Telnet 實作 (續)

昨晚搞定 Telnet 連線程式後, 早上到公司立刻改寫以便測試是否能連線某主機, 然後遠端下指令後, 取得系統資訊, 經過剖析處理後放入資料庫以方便營運管理. 改寫的程式參考前篇文章 :

# Java 的 Telnet 實作

此主機連線後會先要求輸入帳號與密碼認證 :

Enter User Name
>asabulu

Enter Password
>********

因此這裡必須持續攔截輸入串流是否出現 "Enter User Name" 以及 ">", 是的話就將帳號寫入輸出串流, 然後再攔截輸入串流是否出現 "Enter Password" 以及 ">", 是的話就將密碼寫入輸出串流, 這樣就可以登入系統, 可以下達指令了, 例如顯示某資料表內容. 此系統在顯示結束時會以 "BOTTOM" 字串結尾, 因此可用來辨認下達一個指令後, 伺服主機回應的資料是否列印完畢, 達成同步的目的.

之前使用 Javascrip 去呼叫 Putty 做 Telnet 連線取得資料的做法, 因為 Javascript 無法取得輸出入串流, 因此無法與主機同步, 下達指令後還要預估資料要花多少時間才會列印完畢, 然後安插適當的 wait 秒數, 才能下達下一個指令, 否則不同資料表的內容就會前後穿插列印, 導致後續剖析程式分析錯誤. 這種不同步的通訊方式現在看起來還真可笑, 但卻成功運作了兩年之久.



import java.io.*;
import java.net.*;
public class test9_1 {
  static Socket socket;
  static BufferedInputStream bis;
  static BufferedReader r;
  static PrintWriter w;
  public static void main(String[] args) {
    try {
      String host="aa.bbb.cc.dd";  //Telnet 伺服主機
      int port=23;
      String usr="asabulu\n";  //帳號
      String pwd="blabla\n";  //密碼
      if (connect(host,port,usr,pwd)) {System.out.println("connected");}
      else {System.out.println("not connected");}
      socket.close();      
      }
    catch (Exception e) {e.printStackTrace();}
    }
  public static boolean connect(String host,String usr,String pwd) {
    return connect(host,23,usr,pwd);  //預設 port 23
    }
  public static boolean connect(String host,int port,String usr,String pwd) {
    try {
      socket=new Socket(host, port);
      socket.setKeepAlive(true);
      bis=new BufferedInputStream(socket.getInputStream());
      w=new PrintWriter(socket.getOutputStream(),true);
      if (readUntil("Enter User Name")==null) {return false;}
      if (readUntil(">")==null) {return false;}
      Thread.sleep(2000);
      send(usr);
      Thread.sleep(500);
      if (readUntil("Enter Password")==null) {return false;}
      if (readUntil(">")==null) {return false;}
      Thread.sleep(500);
      send(pwd, false);  //不於本機顯示密碼
      Thread.sleep(500);
      if (readUntil(">")==null) {return false;}
      Thread.sleep(2000);
      send("lis table aaa;");
      if (readUntil("BOTTOM")==null) {return false;}
      Thread.sleep(5000);
      return true; // connect OK
      }
    catch (Exception e) {e.printStackTrace();return false;}
    }
  public static void send(String command) {
    send(command, true);  //預設本機顯示應傳送之命令
    }
  public static void send(String command, boolean echo) {  //傳送指令
    try {
      w.println(command);
      w.flush();
      if (echo) {System.out.println(command);}  //顯示所傳送之指令      
      }
    catch (Exception e) {e.printStackTrace();}
    }
  public static String readUntil(String pattern) {
    try {
      char lastChar=pattern.charAt(pattern.length()-1);   //紀錄要攔截的最後一個字元
      StringBuffer sb=new StringBuffer();  //暫存輸入串流讀入之內容
      char ch=(char)bis.read();  //一次讀取一個字元  
      while(true) {   //無限迴圈
        System.out.print(ch);  //顯示讀入之字元
        sb.append(ch);  //讀入之字元存入緩衝器
        if (ch==lastChar && sb.toString().endsWith(pattern)) {
          return sb.toString();  //找到目標字串, 傳回讀取之串流字串 (可用來存檔)
          }    
        ch=(char)bis.read(); /續讀
        }
      }
    catch(Exception e) {e.printStackTrace();}
    return null;
    }
  }

實際測試可成功登入主機並下達顯示資料表之命令. 此處我還沒有處理主機傳回資料的存檔問題, 雖然這是我真正的目的, 但我想把程式改成物件化與多緒執行再來.




2014年5月1日 星期四

Java 的 Telnet 實作

這兩天在看湯秉翰的 "網路程式設計初學指引" (博碩), 第八章是講 TELNET 通訊協定, 看後獲益良多, 這本書是我五本網路程式書籍中寫得最棒的一本, 淺顯易懂, 特別是作者功力深, 光是 TELNET 協定實作方面, 沒有一本書像這本這樣從協定觀念簡介, 到實際用 Java 實作都一五一十介紹的. 以下是閱讀摘要 :
  1. Telnet 協定係主從式架構, 客戶端與伺服端使用 TCP 傳輸層建立連線, 利用 port 23 進行對話, 它只支援文字模式介面. 其規範文件參考 RFC854. 
  2. TELNET 協定內容主要有四 : (1) NVT (2) 命令與資料辨識 (3) 選項 (4) 終端模式
  3. 因為主從兩方控制字元可能不同, 因此 TELNET 採用了 NVT (Network Virtual Terminal) 網路虛擬終端機作為中介. 客戶端與伺服端互傳資料時均須符合 NVT 規定, 以 ASCII 碼傳送資料.
  4. NVT 字元集有兩類 : (1) 命令 (2) 資料, 前者最高位元為 1, 後者為 0. 所有的命令以 255 開頭, 稱為 IAC (Interprete As Command), 當收到 255 時, 表示後續字元都是命令 (控制字元), 否則都屬於資料.
  5. NVT 僅僅是 TELNET 的基本功能, 像伺服端要不要回應 (ECHO), 通知終端機型式或畫面字元寬度等並未在 NVT 中規定, 而是透過跟在 IAC 後面的選項 (Option) 或子溝通選項 (sub-negotiation) 來補強雙方溝通用語. 
  6. TELNET 使用 DO (253), DONT (254), WILL (251), WONT (252) 四個詞彙來溝通選項 :
    DO : 要求對方執行某選項.  或回應認同對方想要執行的選項.
    DONT : 要求對方停止已經在執行之選項, 或回應拒絕對方所要求執行之選項
    WILL : 表示本身將執行某選項, 或回應認可或確認對方所要求執行的選項
    WONT : 拒絕對方的 DO 要求
    所以如果要求對方執行某選項, 對方也答應執行的話, 是 DO-WILL; 對方不同意就是 DO-WONT, 本身想要執行某選項, 對方也認同是 WILL-DO; 對方不認可就是 WILL-DONT 
下面是我從書中範例改寫, 用來測試公司主機用的, 因為不需要中文, 因此拿掉 BIG5 碼轉換. 此程式可以順利連線該主機的 Telnet Server, 經由該範例可以深刻了解應用層協定對話的方式 :

import java.io.*;
import java.net.*;

public class test {
  public static void main(String[] args) {
    String host="localhost";  //這裡用 localhost 代替, 實際使用主機 IP
    int port=23;
    telnet(host,port);
    }
  public static void telnet(String host, int port) {
    Socket socket;
    InputStream in;
    OutputStream out;
    try {
      socket=new Socket(host, port);
      in=socket.getInputStream();
      out=socket.getOutputStream();
      while (true) {
        int data=in.read();
        if (data==255) { //IAC:Interpre As Command (後面是控制指令)
          int tone=in.read();  //第一個 Byte=溝通類型
          int option=in.read();  //第二個 Byte=選項
          switch (tone) {        //檢查伺服端傳來的溝通類型
            case 250 : {          //SB (Sub-negotiation Begin) : 子溝通選項
              switch (option) { //只實作終端機型態
                case 24 : {       //Negotiate terminal type
                  //read remaining 3 bytes from server 後面還有三個 byte 須讀完
                  in.read();      //"1":SEND
                  in.read();      //"255":IAC
                  in.read();      //"240":SE
                  //reply with terminal type="VT100" 回覆伺服器 VT100
                  out.write(255); //IAC
                  out.write(250); //SB
                  out.write(24);  //Terminal type
                  out.write(0);   //"IS"
                  out.write("VT100".getBytes());
                  out.write(255); //IAC
                  out.write(240); //SE
                  out.flush();
                  }
                }
              break;
              }
            case 253 : { //DO (Request or Allow option) 要求我方執行
              if (option==24) { //Allow option : terminal type
                if (tone==253) { //DO
                  out.write(255);     //IAC
                  out.write(251);     //WILL
                  out.write(option);  //Allow option
                  out.flush();
                  }
                else if (tone==251) { //WILL  認可我方要求
                  out.write(255);     //IAC
                  out.write(253);     //DO
                  out.write(option);  //DO option
                  out.flush();
                  }
                }
              break;
              }
            default : { //Deny option 預設 : 拒絕選項
              if (tone==253) {      //DO:reply with WONT
                out.write(255);     //IAC
                out.write(252);     //WONT
                out.write(option);  //rejected option
                out.flush();
                }
              else if (tone==251) { //WILL:reply with DONT
                out.write(255);     //IAC
                out.write(254);     //DONT
                out.write(option);  //rejected option
                out.flush();
                }
              } //end of default
            } //end of switch
          } //end of if
        else { //NOT IAC : display received
          System.out.print((char)data);
          }
        }    
      }
    catch (Exception e){System.out.println(e);}
    }
  }

其實不需要從 RFC854 實做 Telnet, 直接以字元 IO 方式讀取伺服器回應再傳送指令也是可以的, 首先在下列網站找到一個 Telnet 伺服器 :

# http://www.telnet.org/htm/places.htm

挑選了其中的 rainmaker.wunderground.com 這個 TELNET 伺服器作為測試標的, 當以 TELNET 連線此 IP 時, 首先會出現 "Press Return to continue:" 提示文字, 按 ENTER 後出現 "Press Return for menu or enter 3 letter forecast city code--" 回應, 隨便輸入 3 個字元按 ENTER 後, 出現選單. 

我參考了下列兩個網站資料, 改寫為如下之範例 :

# http://letrungthang.blogspot.tw/2011/12/telnet-in-java.html
# http://stackoverflow.com/questions/6399557/java-simple-telnet-client-using-sockets


import java.io.*;
import java.net.*;
public class telnet {
  static Socket socket;
  static BufferedInputStream bis;
  static BufferedReader r;
  static PrintWriter w;
  public static void main(String[] args) {
    try {
      String host="rainmaker.wunderground.com";
      int port=23;
      if (connect(host,port)) {
        System.out.println("connected");
        String prompt1="Press Return to continue:";
        String prompt2="city code-- ";
        if (readUntil(prompt1) != null) {
          send("\n");
          Thread.sleep(500);
          if (readUntil(prompt2) != null) {
            send("TPE\n");
            Thread.sleep(500);
            System.out.println("connected");
            }
          }
        }
      else {System.out.println("not connected");}
      socket.close();      
      }
    catch (Exception e) {e.printStackTrace();}
    }
  public static boolean connect(String host,int port) {
    try {
      socket=new Socket(host, port);
      socket.setKeepAlive(true);
      bis=new BufferedInputStream(socket.getInputStream());
      w=new PrintWriter(socket.getOutputStream(),true);
      return true; // connect OK
      }
    catch (Exception e) {e.printStackTrace();return false;}
    }
  public static void send(String value) {
    try {
      w.println(value);
      w.flush();
      System.out.println(value);
      }
    catch (Exception e) {e.printStackTrace();}
    }
  public static String readUntil(String pattern) {
    try {
      char lastChar=pattern.charAt(pattern.length()-1);
      StringBuffer sb=new StringBuffer();
      int numRead=0;
      char ch=(char)bis.read();    
      while(true) {
        System.out.print(ch);
        numRead++;
        sb.append(ch);
        if (ch==lastChar) {
          if (sb.toString().endsWith(pattern)) {return sb.toString();}
          }              
        if (bis.available()==0){break;}
        ch=(char)bis.read();
        if (numRead > 2000) {break;} // can not read the pattern
        } //end of while
      } //end of if
    catch(Exception e) {e.printStackTrace();}
    return null;
    }
  }



參考資料 :

# 逢甲大學資訊工程學系專題報告: 實作 Telnet Client
# 瞭解 Telnet
# java simple telnet client using sockets
# Telnet client library
# Places to telnet