iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 17
2
自我挑戰組

Linux學習系列 第 17

AWS EC2 設定Ubuntu 、了解TCP與UDP、查看封包內容

網址:

Computer Networking Tutorial - 28 - Connecting to a Server with PuTTY
Computer Networking Tutorial - 29 - Creating SSH Keys
Computer Networking Tutorial - 30 - Changing the Default SSH Port

沒有ssh連線時,會出現這個
https://ithelp.ithome.com.tw/upload/images/20181030/20111994TAIyXX8NDx.png
畫面裡的login下面有個綠色框框,如果想要取消,右鍵-->changing setting-->window-->appearance-->Verticle line-->Cursor blinks-->apply
https://ithelp.ithome.com.tw/upload/images/20181030/20111994GloQIfejPz.png

AWS的Ubuntu預設的使用者是ubuntu,現在要來創個使用者ted

1 adduser ted(錯誤 要是root身分才能執行這個指令)
2 su (錯誤,因為還不知道root身分的密碼)
3 sudo passwd root(設定root的密碼)
4 su (輸入密碼後換成root使用者)
5 adduser ted(成功)(接著要設定一些東西,除了密碼以外都可以按enter跳過))
https://ithelp.ithome.com.tw/upload/images/20181030/201119947WFjJLf0iJ.png

接著登入ted使用者,並想要把ted這個使用者切換成ubuntu這個使用者

1 su ted(登入成功)
2 su ubuntu(登入ubuntu使用者,錯誤,因為不知道密碼)
3 sudo passwd ubuntu(設定ubuntu使用者的密碼,錯誤,因為ted並沒有sudo這個group,可以用指令groups來查看使用者有什麼group)
4sudo passwd ted(這個步驟沒什麼意義,只是忘記有設定過ted使用者的密碼。sudo還沒被加進到ted的group,所以錯誤)
https://ithelp.ithome.com.tw/upload/images/20181030/20111994NnL3IQ0PIe.png

接著把sudo加進ted的group,並且從ted這個使用者切換成ubuntu這個使用者

1su(切換到root使用者)
2sudo qpasswd –a ted sudo(把sudo加到ted的群組,這樣ted使用者才能使用sudo,最近試了一下好像找不到qpasswd指令,不過方法很多,隨便找都有,所以可以改成sudo adduser ted sudo)
3su ted(切換到ted使用者)
4groups(檢查ted的group有沒有sudo)
5su ubuntu(錯誤,因為還不知道ubuntu使用者的密碼)
6sudo passwd ubuntu(設定密碼,設定成功)
7 su ubuntu(可以從ted使用者切換到ubuntu使用者了)
https://ithelp.ithome.com.tw/upload/images/20181030/201119943d55Cc7KKA.png

使用putty產生public key和private key,可是在AWS設定機器時,就已經選擇製作一個公鑰檔了,所以這個步驟不需要
https://ithelp.ithome.com.tw/upload/images/20181030/20111994xSJzwAII07.png

接著講到ubuntu有個資料夾.ssh裡有個檔案叫authorized_keys存公鑰
https://ithelp.ithome.com.tw/upload/images/20181030/20111994zUP9c4p7Kg.png

伺服器存公鑰,要連伺服器的人要有私鑰
除了之前用過的putty.exe-->auth可以放ppk檔外
還有另一種方法也可以放ppk檔:開啟plink.exe
https://ithelp.ithome.com.tw/upload/images/20181030/20111994Ffsp9yjUQE.png
選擇私鑰(Add Key)
接著再用putty.exe就可以開虛擬機器了
https://ithelp.ithome.com.tw/upload/images/20181030/20111994zwgkHD3WEr.png

接著講到修改port,可以比較安全,不然駭客會比較好攻擊,因為預設ssh的port都是22
sudo nano /etc/ssh/sshd_config(到文字編輯器修改port)
修改完後執行 sudo service ssh restart
https://ithelp.ithome.com.tw/upload/images/20181030/20111994aLtLrcc59g.png
文字編輯器畫面:
修改port,把22改成別的數字,但不能是其他協定的port,像:80。這邊改成8888
https://ithelp.ithome.com.tw/upload/images/20181030/20111994AmPsilggsO.png
接著如果再回在putty,port如果沒有修改還是22的話,會出現這個
可是port改成8888還是沒辦法登入ubuntu
https://ithelp.ithome.com.tw/upload/images/20181030/20111994OOuVjYiS6J.png
因為要修改防火牆,要新增8888
https://ithelp.ithome.com.tw/upload/images/20181030/20111994L6ikjt6Gjk.png
接著就可以登入囉

接著來了解TCP

TCP與UDP
鳥哥的 Linux 私房菜
TCP 三向交握 (Three-way Handshake)
傳輸控制協定

傳送層:

1 IP協定只確保封包交換設備之間的傳輸﹐並沒有提供一套機制來確保數據的傳輸。

2 封包之抵達常是不依序的﹐或是會發生重複傳送的情形。因此必須提供一套網路技術﹐以達成更可靠和有效的傳送。

3 TCP提供的是一個可靠的資料流傳送服務;UDP提供的是一個非可靠的資料流傳送服務。

可靠性傳送服務的特性:

如圖:發送方傳送封包1給接收方,發送方啟動計時器,如果計時器超出時間,發送方就會認為封包1不見了,於是再傳一次封包1,再啟動計時器,如果正常時間,發送方就會收到接收方的Acknowledge Number,並取消定時器
http://www.pcnet.idv.tw/pcnet/network/tcp2.png
但是這會有問題:封包沒正常時間抵達,所以才重發封包,但如果後來抵達了,不就變成兩個封包重複了?待會再說明

滑動視窗(Sliding Window)
接著會有問題:每一個單一封包都需要需要等待前面的封包確認之後才進行傳送的話,將會導致整個連線過程時間的增加,同時也會造成頻寬的浪費。
解決方法:多重發送和多重確認的技術

如圖: 發送方一次發送三個封包出去,如果接收方夠順利,就會向發送端確認全部三個封包(傳送ACK1、ACK2、ACK3)
http://www.pcnet.idv.tw/pcnet/network/tcp4.png

通訊埠口(port)

What is a TCP port and how is it used during connections?
影片中講得很簡單,就是當你要向一個server看網頁時,如果這個server同時有mail和網頁的功能,他不知道你是要看網頁還是要傳mail,所以當你要求網頁時,可能會收到mail,所以當要傳送資料時,不只要有IP地址(IP地址只知道伺服器的位置,但是不知道要用伺服器的什麼功能),還要有port(知道你要用伺服器的哪個功能)
什麼是Well-Known Port?
常用的服務有固定的port,像是:
網頁就是http或https-->80或443
File Transfer Protocol(檔案傳輸協定)服務-->21
SMTP(Simple Mail Transfer Protocol,簡單郵件傳輸協議),mail-->25
Secure Shell(安全外殼協定,簡稱SSH)-->22

常用 TCP Port作用(各種Port介紹):
常用 TCP Port作用(各種Port介紹)

在 Linux 的 /etc/services 這個檔案有Well-Known Port及其對應的服務名稱。
要注意有些是tcp的,有些是udp的。
指令:cat /etc/services | more
https://ithelp.ithome.com.tw/upload/images/20181030/20111994z04COpeN25.png

Socket Pair

一個Socket就是由一個IP與一個Port來定義的,所以就是這四個內容
來源位址(Source Address)
來源埠口(Source Port)
目的位址(Destination Address)
目的埠口(Destination Port)

TCP Header:

https://3.bp.blogspot.com/-E3Y5g4jU29U/Vp7t6qwR2gI/AAAAAAAGeXs/FAm0_8uwivI/s0/phppmu5Ws
https://s3.notfalse.net/wp-content/uploads/2016/12/12003643/TCP-Header-Format.png

Source Port & Destination Port:

來源端和目的端的埠口號碼

Sequence Number:

封包序號。當資料要從一台主機傳送去另一台主機的時候,發送端會為封包建立起一個起始序號,然後按照所傳送的資料長度(位元組數值),依次的遞增上去﹔根據此一原理,我們可使用遞增之後的值來作為下一個封包的序號。

Acknowledge Number:

回應序號。當接收端接收到TCP封包並通過檢驗確認之後,會依照發送序號、再加上資料長度產生一個回應序號,附在下一個回應封包送回給對方(無需額外的送出專門的確認封包),這樣就知道剛才的封包已經被成功接收到了。

發送端的封包的計時器達到期限時,還沒接收到Acknowledge Number的話,就會認為該封包丟失了並加以重送。但如果重發封包之後才接Acknowledge Number呢?這時候接收端收到兩個一樣的封包要怎麼辦呢?就根據Sequence Number來判斷該封包是否被重複發送,如果是的話,將之丟棄不做任何處理就是了。

TCP 第一次:
https://ithelp.ithome.com.tw/upload/images/20200610/20111994oKYsxw81eD.png

TCP 第二次:
https://ithelp.ithome.com.tw/upload/images/20200610/201119941odRfKJfte.png

TCP 第三次:
https://ithelp.ithome.com.tw/upload/images/20200610/20111994MiE27dHyEi.png

如圖:內容來自 :TCP與UDP
https://ithelp.ithome.com.tw/upload/images/20181030/20111994qPeNt8zKjH.png
步驟1:發送端-->發送第一個封包,封包的Sequence Number是1234567,資料長度(位元組數值)是:100bytes

步驟2:接收端-->收到第一個封包,並將100bytes的資料放到接收緩衝區

步驟3:接收端-->發出一個回應封包,封包的Acknowledge Number是第一個封包的Sequence Number+資料長度(位元組數值)。1234567+100=1234667

步驟4:發送端-->收到回應封包,比對Acknowledge Number是否等於第一個封包的Sequence Number+資料長度(位元組數值),比對正確,從發送緩衝區扣掉100bytes,
也就是說下一個封包的Sequence Number就是回應封包的Acknowledge Number。
為什麼呢?因為TCP 的Acknowledge Number除了代表有接收到封包,還會指出接收端下一個期望接收到的Sequence Number。

步驟5:發送端-->發送第二個封包,第二個封包的Sequence Number就是1234667等於回應封包的Acknowledge Number,然後第二個封包資料長度(位元組數值)是:150bytes

步驟6:接收端-->收到第二個封包,並將150bytes的資料放到接收緩衝區

步驟7:接收端-->接收端也開始像發送端一樣傳送有Sequence Number的封包了,所以回應封包的Sequence Number是7654321,Acknowledge Number是Seq+data_len,就是1234667+150=1234817

步驟8:發送端-->收到封包,比對Acknowledge Number是否等於第二個封包的Sequence Number+資料長度(位元組數值),比對正確,從發送緩衝區扣掉150bytes,並將回應封包的50byte放到接收緩衝區

步驟9:發送端-->發送第三個封包,且回應確認剛才接收的資料,所以第三個封包的seq=1234817(等於回應封包的ack),ack=7654371(就是回應封包的seq+data_len)

步驟10:接收端-->收到第三個封包,比對Acknowledge Number是否等於Sequence Number+資料長度(位元組數值),從發送緩衝區扣掉50bytes,並將第三個封包的200bytes放入接收緩衝區內。

什麼是ACK_bit="on"?
Contral Flag裡的Acknowledge field significant
Acknowledge field significant為1的時候,表示此封包的Acknowledge Number是有效的。一般都會為1。如圖,有ack的都有ACK_bit="on"。

Data Offset (HLEN)

這是用來記錄表頭長度用的,和IP封包的IHL差不多。如果Options和Padding沒有設定的話,也就只有5列的長度;每列有32bit;也就是4byte;那麼,5列就是20byte了,20這個數值換成16進位就成了0x14。

Reserved

這是保留區間,暫時還沒被使用。

Code、Contral Flag(控制標誌碼)

控制旗標,共有6個 bits,分別代表6個控制碼,若為1則為啟動。

Urgent data (URG)

當URG被設定為 1 的時候,就表示這是一個攜有緊急資料的封包,接收端需優先處理。

Acknowledge field significant (ACK)

當ACK為1的時候﹐表示此封包的Acknowledge Number是有效的,也就是用來回應上一個封包。一般都會為 1。前面那張圖Sequence number和Acknowledge number的例子中﹐只有第一個封包沒有設。

Push function(PSH)

如果PSH為1的時候,要求發送端連同傳送緩衝區的其它封包應立即進行傳送,而無需等待緩衝區滿了才送。接收端必須儘快將此資料交給程式處理。
通常應該是server 發給 client的訊息?(不是,兩邊都可以發這個訊息)
https://ithelp.ithome.com.tw/upload/images/20200610/2011199483hQ1GSUnN.png

Reset(RST)

如果RST為1的時候﹐連線會被馬上結束,而無需等待終止確認手續。這也就是說, 這是個強制結束的連線,且發送端已斷線。

Synchronize sequence number(SYN)

如果SYN 為1時﹐表示要求雙方進行同步處理﹐也就是要求建立連線。
觀察建立連線時,前三次的TCP,前兩次會有SYN=1:

第一次:
https://ithelp.ithome.com.tw/upload/images/20200610/20111994GZpJ9Xw23c.png

第二次:
https://ithelp.ithome.com.tw/upload/images/20200610/20111994m9SDG8a4xt.png

第三次:
https://ithelp.ithome.com.tw/upload/images/20200610/201119941MIoKB4y1r.png

No more data fro sender (FIN)

如果封包的FIN為1的時候﹐就表示傳送結束,然後雙方發出結束回應,進而正式進入 TCP 傳送的終止流程。

TCP/IP的Three-Way Handshake: TCP 連線建立的前提。只有通過 handshake才能進入真正的連線建立狀態(像前面例子的Acknowledge Number和Sequence Number),否則不能建立連線。
這篇文章清楚易懂:
TCP 三向交握 (Three-way Handshake)

https://s3.notfalse.net/wp-content/uploads/2016/12/24160105/Three-way-Handshake-ex2.png

Window

這個就是有關滑動視窗(Sliding Window)了,在 TCP 封包表頭的這個欄位,可得知對方目前的接收緩衝區大小( bytes ),從而決定下一個傳送Window的大小。當 Window=0時,代表緩衝器已經額滿,所以應該要暫停傳輸資料。Window的單位是 byte。

觀察telnet ptt2:
參考使用-telnet-診斷各種伺服器與網路連線問題
Win 10開啟Telnet用戶端
[Day 5] 我的PTT哪有這麼不安全
https://packetlife.net/media/library/13/Wireshark_Display_Filters.pdf

傳給ptt2:
https://ithelp.ithome.com.tw/upload/images/20200610/20111994yX8mlwuoJp.png

ptt2傳給我:
https://ithelp.ithome.com.tw/upload/images/20200610/201119945ZgLUrsACQ.png

Checksum

當資料要傳送出去的時候,發送端會對資料進行一個校驗的動作,然後將校驗值填在這裡;當接收端收到封包之後,會再對資料進行校驗,再比對校驗值是否一致。若結果不一致則認為資料已損毀,並要求對方重送。

Urgent Pointer

這個欄位是在Code欄位內的URG = 1時才會產生作用。可以告知緊急資料所在的位置。不過這種情形非常少見,例如當資料流量超出頻寬的時候,系統要求網路主機暫緩發送資料,所有主機收到這樣的信息,都需要優先處理。此時接收端會進入緊急狀態,當緊急資料處理完畢後,接收端就會回復正常的接收狀態。

Option

這個選項比較少用。當那些需要同步動作的程式,如Telnet,要處理好終端的交互模式,就會使用到option來指定資料封包的大小,因為 telnet 使用的資料封包都很少,但又需要即時回應。
Option 的長度要麼是 0 ,要麼就是32bit的整倍數,即使資料不足數,也要使Padding(補足欄位)來填夠。

Padding(補足欄位)

如同IP封包需要有固定的32bits表頭一樣,Options由於欄位為非固定,所以也需要Padding欄位來加以補齊才行。同樣也是32 bits的整數。

UDP

UDP 的全名是:『User Datagram Protocol, 用戶資料流協定』,UDP與TCP不一樣, UDP不提供可靠的傳輸模式,因為他不是連線導向的一個機制,這是因為在 UDP 的傳送過程中,接受端在接受到封包之後,不會回覆回應封包 (ACK) 給發送端,所以封包並沒有像 TCP 封包有較為嚴密的檢查機制。

UDP 比較適合需要即時反應的一些資料流,例如影像即時傳送軟體等, 就可以使用這類的封包傳送。也就是說,UDP傳輸協定並不考慮連線要求、連線終止與流量控制等特性,所以使用的時機是當資料的正確性不很重要的情況,例如網路攝影機。

有些服務是同時提供TCP與UDP的,像是:查詢主機名稱的DNS服務就同時提供了 UDP/TCP 協定。由於UDP較為快速,所以我們 client 端可以先使用 UDP來與伺服器連線。但是當使用UDP連線卻還是無法取得正確的資料時,便轉換為較為可靠的TCP傳輸協定來進行資料的傳輸
如圖:
http://www.pcnet.idv.tw/pcnet/network/tcpip_suit.png

UDP Header

https://notes.shichao.io/tcpv1/figure_10-2.png

Source Port & Destination Port:

跟TCP的Port一樣。

Message Length:

整個UDP封包的長度,以位元組為單位( byte ),最小值為8,也就是UDP Header的大小

Checksum:

封包及資料的校驗值,跟TCP的checksum功能一樣,用作資料完整性的檢測依據。然而,關於UDP的checksum計算卻有點複雜,因為其值必需連同一個所謂的UDP 虛擬表頭(UDP Pseudo Header)一起計算的。

UDP 虛擬表頭(UDP Pseudo Header):
https://ithelp.ithome.com.tw/upload/images/20190108/20111994mJpBHOnkpV.png

之所以稱為虛擬,是因為其中的 Source IP Address 與 Destinatin IP Address 並不出現在UDP封包中,而是在IP封包中。但在進行校驗的時侯,發送端與接收端則根據此"虛擬"的表頭及資料進行。然而,此表頭是不會出現在任何封包中的。

TCP UDP感覺起來還是很抽象,所以可以簡單地用些工具觀察

使用C# 寫程式:
程式來源:
[C#.NET] 簡易TcpListener/TcpClient使用方式

之後原本想直接用Wireshark來觀察的,但是localhost好像不能。
所以又載了這個:
How to capture localhost packets
抓包工具之:Wireshark 和 RawCap

結果:
前面這段是ipv4的資訊:
https://ithelp.ithome.com.tw/upload/images/20200329/20111994QyX1OjF53M.png

顯示的是16進位數字 , 然後16進位 代表一個數字 有4個bit,這時候就可以回去看 ip或tcp的表頭格式, 核對每個內容 的大小。

像是data,就是傳輸的資料了 ,但是 只有數字 會實際顯示在右邊的樣子,其他內容要怎麼看?
https://ithelp.ithome.com.tw/upload/images/20200329/20111994wotWRBz8ZA.png

用C#程式檢查,參考:
convert-byte-array-to-string-csharp
我是傳這個字串:"顧客端送資料012345678910 5" , 所以我把 這個字串 轉成 16進位byte ,就應該要和左邊的那串數字一樣。

byte[] bytes = Encoding.Default.GetBytes("顧客端送資料012345678910 5");
Console.WriteLine("Byte Array is: " + String.Join(" ", bytes));

結果:

Byte Array is: 233 161 167 229 174 162 231 171 175 233 128 129 232 179 135 230 150 153 48 49 50 51 52 53 54 55 56 57 49 48 32 53

然後再把 數字變回字串 核對:

string str = Encoding.Default.GetString(bytes);
Console.WriteLine("The String is: " + str);

結果

The String is: 顧客端送資料012345678910 5

但是233 161 167 ...是十進位 ,所以把10進位 轉成 16進位字串查看(16進位有abc...之類的,所以被當成字串,而不是數字)

for (int i = 0; i < bytes.Length; i++)
{
    Console.Write( Convert.ToString(bytes[i], 16)+" ");
}
e9 a1 a7 e5 ae a2 e7 ab af e9 80 81 e8 b3 87 e6 96 99 30 31 32 33 34 35 36 37 38 39 31 30 20 35

這樣就知道data實際內容了

那如果是要把16進位轉成字串呢?
想法:16進位 -- > bytearray -->中文字串

string input = "e9 a1 a7 e5 ae a2 e7 ab af e9 80 81 e8 b3 87 e6 96 99 30 31 32 33 34 35 36 37 38 39 31 30 20 35";
input = Regex.Replace(input, @"[^a-zA-Z0-9]+", ""); //把英文和數字以外的char去掉
string pattern = @"([a-zA-Z0-9]{2})";
MatchCollection mc = Regex.Matches(input, pattern);
byte[] bytes = new byte[mc.Count];
for (int i = 0; i < mc.Count; i++)
   bytes[i] = Convert.ToByte(mc[i].Value, 16);
//byte轉字串
String mystring01 = Encoding.UTF8.GetString(bytes);
Console.WriteLine($"mystring01?{mystring01}");
顧客端送資料012345678910 5

參考資料:在 Windows Form 中使用正規式 Regex 來解析字串


上一篇
AWS EC2 安裝Linux(了解putty、SSH) 和 了解 EC2種類
下一篇
Linux dns-nameservers
系列文
Linux學習30

尚未有邦友留言

立即登入留言