SSH tunnel (auto-ssh)

SSH tunnel (auto-ssh)

เคยกันหรือเปล่าครับ ที่อยากจะ Remote หรือ SSH ไปยังอุปกรณ์ภายในเครือข่ายที่ติดตั้งอยู่ แต่ดัดมี Faiwall หรือ NAT มาขวางอยู่ซึ่งปกติเราจะทำการ Forwort port กันไปใช่มั้ยละครับ แต่หากเราอยู่ในสภาพแวดล้อมที่ ไม่สามารถแก้ไขได้ละ เช่นเราใช้ 3G เป็นตัวรับอินเทอร์เน็ต (ผู้ให้บริการ 3G จะจ่าย Private IP Adress มาให้เรา) หรือไม่ก็หากเราใช้งานอยู่ในองค์กรที่เราไม่สามารถไป ยุ่งเกี่ยวกับ Network ได้นั้นก็เท่ากับเราไม่สามารถจะ Remote หรือ SSH กลับมายัง Raspberry Pi ได้เลย ซึ่งมันไม่ใช่… หากท่านรู้จักกับ SSH tunnel และ Reverse SSH Tunneling

เบสิกันก่อน

ดังรูปนะอย่าง Raspberry Pi ปกติแล้วเราจะใช้งาน SSH อยู่บน Port 22 ใช่มั้ยครับ แล้วลองคิดว่าเราได้เอาไปต่อกับ Router ภายในบ้าน แล้วคอมพิวเตอร์ที่เราใช้งานได้ IP Address 192.168.1.5 เราก็สามารถ SSH เข้าไปที่ Raspberry Pi ได้เลยผ่าน Port 22 เพราะเนื่องจากทั้ง 2 อุปกรณ์อยู่ใน Network วงเดียวกัน 192.168.1.xx

และเมื่อเราต้องการจะต้องที่ใช้งาน SSH จากภายนอก Network จึงต้อง Forward port ซึ่งจากภาพบนนั้นจะเห็นว่า จะให้ Port 22 จาก WAN (48.48.48.1) ไปยัง Port 22 ของ LAN (192.168.1.10) ดังนั้นเราก็สามารถเข้าถึง Raspberry Pi ได้จากอินเตอร์ได้สบายยเลย แต่!! การที่เราจะ Forward port ได้นั้นเราต้องมี User & Password ของ Router และ ด้าน WAN ของ Router ก็ต้องเป็น Public IP address ด้วยนะครัช

หาก WAN ของ Router ไม่เป็น Public IP address ละ

จริงๆ แล้วไม่ใช่แค่ WAN ของ Router ไม่เป็น Public IP address รวมไปถึง หากเราใช้อินเทอร์เน็ตอยู่ในองค์กร หรือโรงเรียน มหาวิทยาลัยต่างๆ ที่ค่อนข้างสลับซับซ้อนหรือมี NAT ซ้อนกันหลายชั้นมากอย่างในรูป ซึ่งอีกอย่างที่เหมือนกับในรูปเลยคือ 3G Network ดังนั้นจะเห็นว่าจะให้เราไป Forward port ทุกๆ NAT ก็ดูจะโหดร้ายเกินไป หรือยิ่งยากว่านั้น หากเป็น Network ขององค์กร โรงเรียน มหาวิทยาลัย และ 3G เราไม่มีสิทธิ์เลยที่จะไป Forward port Raspberry Pi ของเราออกไปด้านนอกได้เลย …. จบไม่ต้องทำละ เย้!!

ไม่สิไม่ ทีนี้เราจะ SSH เข้าไปอย่างไรละ ก็ใช้ SSH tunnel ไงละ ฮึมม…นี่ก็เกริ่นนํานานมาก

 

SSH tunnel

คือการสร้างเส้นทางตัดตัดผ่านแล้วไม่สนใจในระบบ Network ว่ามีจะผ่าน Router กี่สิบตัวก็ตาม แบบว่าหากฉันเข้ามาด้วย Port 22 ไปยัง SSH tunnel มันก็จะทะลุไปยังเครื่องด้านขวาเลย (49.49.49.1) เพราะอะไรถึงทำแบบนี้ได้ เพราะระบบอินเทอร์เน็ตนั้น จะมี Firewall (NAT เป็นสับเซตของ Firewall) ที่ทำหน้าที่ป้องกันข้อมูลที่วิ่งจากด้าน WAN –> LAN แต่จากด้าน LAN –> WAN จะปล่อยผ่านไป ดังนั้นเราจึงใช้โอกาสนี้ละสร้างการเชื่อมต่อ SSH tunnel ออกมายังเครื่องคอมพิวเตอร์แทน (49.49.49.1) ทีนี้บนเครื่องคอมพิวเตอร์ขวามือก็จะมี SSH มาเชื่อมต่ออยู่ เราจึงคุยกันได้แล้ว

แต่มีปัญหาอีกเพราะว่าเครื่องคอมพิวเตอร์ขวามือนั้นมันจะต้องเปิด 24 ชม. เพราะเราจะให้ Raspberry Pi สร้าง SSH tunnel มาเชื่อมต่อดังนั้นหากคอมเครื่องนั้นมันไม่ออนไลน์ก็จบ Pi มันก็ไม่รู้จะคุยกลับใครละสิ จึงเป็นที่มาของด้านล่างที่จะมี EC2 มาทำเป็นเครื่องที่คอยรับ SSH Tunnel ที่มาจาก Raspberry Pi เพราะ EC2 นี่มันคงไม่ล่มแน่ๆ แต่หากใครอยากประหยัดหน่อก็ใช้ Raspberry Pi อีกสักตัวเปิดทิ้งไว้แล้ว Forward port ก็ได้เหมือนกัน

ทีนี้เวลาเราจะ SSH ไปยัง Raspberry Pi ตัวซ้ายมือเราก็แค่ SSH ไปยัง EC2 แล้วก็ SSH ไปอีกต่อตามที่ Raspberry Pi ได้สร้าง SSH tunnel ไว้ (อันนี้มีชื่อเรียกไม่ทางการว่า Reverse SSH tunnel เพราะเราทำย้อนทาง) ….. ไม่รู้งงกันเปล่า เอาว่าลองดูรูปด้านล่าง

รูปนี้คือตรง EC2 จะเห็นว่าบนสุดให้ดู IP Address (อันนี้มันรันอยู่บน Alpine ใน Docker) อันนี้ก็ไป Forward port ให้เรียบร้อย แต่หากเป็นบน EC2 ก็ไปปรับ Security list ให้เรียบร้อย ส่วนอันต่อมา ลองเช็คว่ามีอุปกรณ์ตัวใหนบ่างที่ได้สร้าง SSH tunnel มาหาเครื่องตัวนี้บ่างก็จะเห็นว่ามี 2 ตัวคือตัวที่ใช้ Port 10000 กับ 22000 ทีนี้เวลาเราจะ Remote SSH ไปยัง Raspberry Pi ก็แค่พิมพ์

ssh <user>@localhost -p 10000

ก็เป็นอันจบพิธีเลย

Auto SSH

ปัญหาต่อมาที่ตัว Raspberry Pi ที่เราจะสร้าง SSH tunnel มาที่ EC2 นั้นจริงๆ แล้วไม่ต้องลงอะไรเพิ่มเติมเลยเพราะสามารถใช้คำสั่ง ssh -L 9000:imgur.com:80 [email protected] อะไรประมาณนี้ได้แล้ว แต่ก็อย่างที่ว่าละใครจะไปพิมพ์คำสั่งนี้ให้ละในเมื่อเราจะ Remote SSH เข้าไปนิ ดังนั้นจึงต้องหาผู้ช่วยที่จะสร้าง SSH tunnel ให้เราทุกครั้งที่ระบบ Restart หรือขาดการเชื่อมต่อ ผู้ช่วยที่ว่าคือ Auto SSH นั่นเอง ลงง่ายๆ แค่ใช้คำสั่ง

sudo apt-get install autossh

ต่อมาเราต้องสร้าง Key pair เพราะว่าเมื่อทุกครั้งที่ Raspberry Pi เราสร้าง SSH tunnel ไปยัง EC2 จะไม่ต้องมาคอยใส่ password ซึ่งทำได้โดยพิมพ์ sudo ssh-keygen จากนั้นจะมี public key ถูกเก็บอยู่ใน /root/.ssh/id_rsa.pub ให้คัดลอกไปยังเครื่อง EC2 โดยใช่คำสั่ง

scp -P <port EC2> /home/pi/.ssh/id_rsa.pub <user>@<ip adress EC2>:/root/

ต่อไปให้ SSH ไปยังเครื่อง EC2 แล้วใช้คำสั่ง

cat id_rsa.pub >> /root/.ssh/authorized_keys

กลับมาที่ Raspberry Pi แล้วลองพิมพ์ ssh <user>@<ip adress EC2> หากถูกต้องจะเข้าเครื่อง EC2 ได้เลยไม่ต้องใส่ Password

ทดสอบใช้งาน Auto SSH

autossh -p <Port EC2> -M 20000 -N -f -i/home/pi/.ssh/id_rsa -R <Port>:localhost:22 <user>@<ip adress EC2>

จากนั้นลองตรวจสอบบน EC2 ด้วยคำสั่ง netstat -tpln | egrep ' (Proto|ssh) ' จะพบว่ามี SSH tunnel ที่ใช้ Port 25000 เชื่อมต่อเข้ามาแสดงว่าเรามีถูกทางแล้ว

Auto-SSH @ Boot

หลังจากที่รู้ว่ามันใช้งานได้แล้วแน่ๆ ทีนี้เรามาทำให้มันทำงานด้วยตัวเองทุกครั้งที่มันได้เปิดขึ้นมาโดยใช้ Systemd

สร้างไฟล์ Systemd

sudo nano /lib/systemd/system/autossh.service

โดยกำหนดค่าดังต่อไปนี้ แต่อาจจะต้องแก้ไข User ไปตามที่ต้องการ

[Unit]
 Description=autossh
 Wants=network-online.target
 After=network-online.target

[Service]
 Type=simple
 User=pi
 EnvironmentFile=/etc/default/autossh
 ExecStart=
 ExecStart=/usr/bin/autossh $SSH_OPTIONS
 Restart=always
 RestartSec=60

[Install]
 WantedBy=multi-user.target

สร้าง link ไปยัง /etc/systemd/system: โดย

sudo ln -s /lib/systemd/system/autossh.service /etc/systemd/system/autossh.service

สร้าง Config File ของ Auto SSH

sudo nano /etc/default/autossh

sudo nano /etc/default/autosshAUTOSSH_POLL=60
AUTOSSH_FIRST_POLL=30
AUTOSSH_GATETIME=0
AUTOSSH_PORT=<Port>
SSH_OPTIONS="-p <Port EC2> -N -R <Remote Port>:localhost:22 <user>@<ip adress EC2> -i /home/pi/.ssh/id_rsa"

ซึ่งค่าที่ต้องแก้ไขคือ

AUTOSSH_PORT=<Port>: ให้ใส่ค่าที่มากกว่า 10000
<Port EC2>: Port ที่ใช้ติดต่อกับ EC2 ปกติแล้วจะใช้ 22
<Remote Port>: Port ที่ต่อใช้งาน Reverse SSH tunnel ให้ใส่ค่าที่มากกว่า 10000
<user>@<ip adress EC2>: User และ IP Address ของ Serverในที่นี้คือของ EC2

Run Auto SSH

อันดับแรกให้ restart systemctl  ก่อนโดยใช้คำสั่ง

sudo systemctl daemon-reload

ต่อมาให้ใช้คำสั่งนี้ เพื่อเริ่มใช้งาน

sudo systemctl start autossh

และสุดท้าย เพื่อให้ Auto SSH ทำงานทุกครั้งตอน boot

sudo systemctl enable autossh

แล้วลอง Reboot Raspberry Pi ดูว่า Auto SSH ทำงานปกติหรือเปล่า โดยหากทำงานถูกต้องเราไปใช้คำสั่ง netstat -tpln | egrep ' (Proto|ssh) ' อีกครั้งบน EC2 จะพบว่ามีการเชื่อมต่อ SSH เข้ามาตาม Port ที่เราได้กำหนดไว้ก่อนหน้านี้ จากนั้นให้ลอง Reverse SSH tunnel ไปโดยใช้คำสั่ง

ssh pi@localhost -p <Remote Port>

หากใช้งานได้ปกติก็จะได้ดังรูปนี้นะครัช

จบละ…บายยย

ps. เขียนนานมาก bolg นี้ 2 อาทิตบ้าไปแล้วว

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.