การเข้าถึง SSH จากภายในและภายนอก LAN โดยใช้คำสั่งเทอร์มินัลเดียวกัน


10

ฉันมีราสเบอร์รี่ Pi (RPi) และฉันทำการเชื่อมต่อระยะไกลกับมันโดยใช้ ssh ฉันจัดการเพื่อตั้งค่า ssh อย่างถูกต้องเพื่อให้ฉันสามารถเข้าถึง RPi ทั้งจากเครือข่ายท้องถิ่นและจากอินเทอร์เน็ต (โดยใช้พอร์ตเฉพาะที่ฉันเปิดบนเราเตอร์ของฉัน)

สมมติว่าชื่อผู้ใช้johnและ RPi ชื่อraspi:

การเข้าถึง LAN ภายใน

ssh john@192.168.2.7
ssh john@raspi
ssh raspi

นอกการเข้าถึง LAN

ssh -p 1234 john@12.345.67.89
ssh -p 1234 12.345.67.89

แต่ฉันจะทำssh raspiจากนอกระบบ LAN ได้อย่างไร มีวิธีการกำหนดค่า raspi ให้ชี้ไปที่สองที่อยู่ IP หนึ่งใน LAN และหนึ่งผ่านอินเทอร์เน็ตหรือไม่

สิ่งที่ฉันต้องการคือการเข้าถึง RPi ของฉันด้วยวิธีเดียวไม่ว่าฉันจะอยู่ที่บ้านหรือที่ทำงาน


คุณสามารถเรียกใช้เซิร์ฟเวอร์ DNS บน LAN ท้องถิ่นของคุณซึ่งตอบสนองต่อการร้องขอชื่อ "raspi" ด้วยที่อยู่ IP ท้องถิ่นของ LAN ตอนนี้การแก้ไขชื่อเดียวกันกับที่อยู่ภายนอกที่แตกต่างกันนั้นจะต้องมีการใส่ชื่อนั้น (dynamic dns) ในแบบที่มันยังแก้ไขได้ แต่คุณอาจต้องใช้ชื่อที่ยาวกว่า "raspi"
ChuckCottrill

ดูคำถาม & คำตอบนี้: unix.stackexchange.com/questions/61655/…
slm

คำตอบ:


7

มองคำถามของคุณให้ละเอียดยิ่งขึ้นดูเหมือนว่าคุณกำลังใช้คอมพิวเตอร์เครื่องเดียวกันทั้งในและนอก LAN ฉันได้แก้ไขคำตอบของฉันแล้ว:

ในของคุณ~/.ssh/configเพิ่ม:

Host raspi-wan
    HostName 12.34.56.78
    User john
    Port 1234

Host raspi-lan
    HostName 192.168.1.2
    User john
    Port 22

จากนั้นคุณสามารถssh raspi-wanจากภายนอก LAN หรือssh raspi-lanจากภายใน LAN โดยไม่ต้องกังวลกับเซิร์ฟเวอร์ DNS หรือการแก้ไข/etc/hostsสำหรับผู้ใช้ทั้งหมดหรือแม้กระทั่งต้องทำอะไรก็ได้ในฐานะรูท หากคุณต้องการชื่อที่raspiจะแก้ไขแตกต่างกันไปขึ้นอยู่กับว่าคุณอยู่ที่ไหนนั่นอาจจะต้องใช้เวทย์มนต์สคริปต์เชลล์เพื่อตรวจสอบเครือข่ายของคุณและดำเนินการตามนั้น


1
ขอบคุณ DopeGhoti ฉันรู้สึกสะดวกสบายกับโซลูชั่นของคุณที่จะรวม-wanและ-lanpostfix ssh ของฉัน แต่ไม่ชอบUsernameสนาม (ตัวเลือกการกำหนดค่าไม่ดี) มันทำงานได้ดีหากไม่มีมัน
Aeronaelius

2
ฉันขอโทษไวยากรณ์ที่ถูกต้องคือไม่User john UserNameฉันกำลังแก้ไขคำตอบของฉันเพื่อสะท้อนสิ่งนี้และเมื่อคุณได้ตั้งค่าของคุณแล้วคุณสามารถละเว้นชื่อผู้ใช้จากsshบรรทัดคำสั่ง
DopeGhoti

5

สิ่งนี้สามารถทำได้อย่างสมบูรณ์แบบด้วยการตั้งค่า ssh โดยไม่ต้องใช้นามแฝงแยกต่างหากสำหรับ lan และ wan หรือสร้างพอร์ตเพิ่มเติมใด ๆ (แต่คุณต้องการวิธีการตรวจสอบว่าคุณอยู่ใน LAN ของคุณหรือไม่)

ใน~/.ssh/configคุณจะต้องเพิ่มสิ่งนี้:

Match host raspi exec "am_i_outside_of_my_lan"
    HostName 12.345.67.89
    Port 1234

แทนที่am_i_outside_of_my_lanคุณจะต้องวางคำสั่งที่กำหนดว่าคุณอยู่ในเครือข่ายในบ้านของคุณหรือไม่และกลับมาพร้อมกับรหัสออก 0 หากคุณอยู่ข้างนอกและอย่างอื่น

hostสภาพอาจจะเป็นตัวอธิบาย แต่execสภาพใบสำคัญแสดงสิทธิคำอธิบายบางอย่างมันตรงกับเฉพาะเมื่อผลตอบแทนที่ได้รับคำสั่งด้วยรหัส 0 ออกคือ ไม่มีข้อผิดพลาด

ในคำอื่น ๆ สิ่งนี้ทำอะไรเป็นhost raspiส่วนที่ จำกัด กฎนี้เมื่อคุณพยายามที่จะเชื่อมต่อกับโฮสต์ raspi และexec "am_i_outside_my_lan"จำกัด เพิ่มเติมเพื่อที่จะใช้เฉพาะเมื่อคุณเชื่อมต่อจากนอกเครือข่ายภายในบ้านของคุณ ดังนั้นภายในเครือข่ายภายในบ้านของคุณssh user@raspiไม่ตรงกับสิ่งที่มันปกติ ssh -p 1234 user@12.345.67.89แต่นอกของมันตรงกับกฎและมันแทนไม่เทียบเท่า

สำหรับสิ่งที่จะใช้แทนam_i_outside_of_my_lanนั้นขึ้นอยู่กับการตั้งค่าของคุณทั้งหมด ฉันขอแนะนำให้วางคำสั่งในสคริปต์แยกต่างหากแทนที่จะพยายามเขียนแบบอินไลน์เพราะการอ้างอิงดูเหมือนจะยากไปหน่อย

โดยส่วนตัวแล้วฉันใช้สคริปต์ Python ต่อไปนี้เพื่อตรวจสอบว่าฉันอยู่ในเครือข่ายของตัวเอง: (เนื่องจากชื่อโดเมนของฉันได้รับการแก้ไขเป็น IP ท้องถิ่นภายในเครือข่ายของฉันเอง)

#! /usr/bin/env python
import socket, sys

sys.exit(socket.gethostbyname('mydomain.com').startswith('192.168.1.'))

หากคุณไม่มีการตั้งค่าที่คล้ายกันคุณอาจต้องทำอย่างอื่น (ตัวอย่างเช่นคุณสามารถดูชื่อเครือข่ายไร้สายที่คุณเชื่อมต่อหรือสอบถามบริการ what-is-my-ip เพื่อรับ ip ภายนอกของเครือข่ายที่คุณเชื่อมต่อ)


นี่คือคำตอบที่ถูกต้อง; มันเศร้ามากที่คนอื่นมีคะแนนมากกว่า
Jonathan Tomer

@ Jonathanathan Tomer: เพื่อความยุติธรรมฉันตอบคำถามนี้ 3 ปีหลังจากที่ถูกถามในขณะที่คำตอบที่ให้คะแนนสูงกว่าถูกโพสต์ภายในไม่กี่ชั่วโมงดังนั้นจึงเป็นเพียงกรณีของ "นกตัวแรกที่ได้รับหนอน": P (ฉันยังมี ที่จะบอกว่าฉันชอบ Ellis Hoag ที่แตกต่างจากโซลูชั่นทั่วไปนี้ - การใช้ arp นั้นค่อนข้างฉลาดและทำให้วิธีการทั่วไปมีความซับซ้อนมากขึ้นเนื่องจากในคำสั่งการตรวจจับเครือข่ายไม่จำเป็นต้องปรับสำหรับการตั้งค่าเครือข่ายทุกครั้ง)
Aleksi Torhamo

3

บนคอมพิวเตอร์คุณ (connect- ไอเอ็นจีอย่างใดอย่างหนึ่ง) 12.345.67.89คุณสามารถตั้งชื่อโฮสต์สำหรับ เปิด/etc/hostsไฟล์ของคุณและตั้งค่ารายการ DNS:

12.345.67.89    raspi

เครื่องของคุณจะแปลง "raspi" เป็น "12.345.67.89" ซึ่งเป็นส่วนหนึ่งของกระบวนการแก้ไข DNS ในเครื่อง หากคุณใช้หลายเครื่องต้องทำการเปลี่ยนแปลงในแต่ละเครื่องและทุกเครื่อง ปัญหาคือ: ต้องมีการเข้าถึงรูทเพื่อแก้ไข/etc/hostsและคุณอาจไม่ได้มีอยู่ทุกที่

หากคุณต้องการให้ "raspi" เป็นที่รู้จักโดยอัตโนมัติจากที่ใดก็ได้ขออภัยด้วย: ไม่สามารถทำได้ สิ่งนี้จะต้องมีการลงทะเบียนของ "raspi" เป็นชื่อโดเมนซึ่งไม่สามารถเกิดขึ้นได้เนื่องจาก "raspi" ไม่มี TLD และจะไม่ขึ้นอยู่กับ DNS root ของเซิร์ฟเวอร์ใด ๆ อย่างไรก็ตามคุณสามารถลงทะเบียนชื่อโดเมน (สมมุติcfbaptista.meและชี้ไปที่ที่อยู่ IP ของคุณ WAN ด้วยการส่งต่อพอร์ตคุณจะสามารถเข้าถึง Raspberry Pi ของคุณด้วย:

ssh (you@)(raspi.)cfbaptista.me

(ยังคงที่ใช้จ่ายเงินเกือบไม่มีอะไร ... )

ในuser@ส่วนที่เกี่ยวข้องนั้นขึ้นอยู่กับชื่อล็อกอินของคุณในเครื่องต่างๆ หากคุณมีชื่อเดียวกันในเครื่องเชื่อมต่อและในรีโมทนั้นไม่จำเป็นต้องระบุ ถ้าไม่คุณต้องระบุว่าคุณเป็นใครในเครื่องระยะไกล


หมายเหตุ: ดังที่กล่าวไว้ในคำตอบอื่น ๆ คุณสามารถสร้างนามแฝงโฮสต์ในการกำหนดค่า SSH ของคุณซึ่งแน่นอนว่าไม่จำเป็นต้องใช้รูท
strugee

แน่นอนที่สุด! นี่คือลิงค์เล็ก ๆ น้อย ๆ : collectiveidea.com/blog/archives/2011/02/04/how-to-ssh-aliases
John WH Smith

0

เป้าหมาย: ssh raspiควรทำงานภายใน LAN และบนอินเทอร์เน็ตสาธารณะ

ในการทำเช่นนี้คุณต้องตรวจสอบให้แน่ใจว่าชื่อนั้นได้รับการแก้ไขเป็น IP ภายในบน LAN และ IP สาธารณะจากภายนอก

raspi.yourdomain.comครั้งแรกที่คุณควรจะได้รับชื่อโดเมนเช่น ตรวจสอบhttp://freedns.afraid.org/สำหรับโดเมนฟรีสำหรับใช้งานอดิเรก ชี้โดเมนด้วย IP สาธารณะของคุณ

สำหรับ LAN ฉันแนะนำให้ใช้ DNSMasq เฟิร์มแวร์ DD-WRT ที่เปิดอยู่นั้นรวมเข้ากับ DNSMasq อย่างแน่นหนาเพื่อใช้กับ DHCP และ DNS คุณต้องบอกโดเมนการค้นหาของคุณ ("yourdomain.com") และจะกำหนดชื่อ DNS โดยอัตโนมัติตามชื่อที่ลูกค้าร้องขอ เพื่อให้งานนี้ raspi ของ / etc / raspiชื่อโฮสต์ควรอ่าน

เมื่อตั้งค่านี้แล้ว raspi.yourdomain.com ควรแก้ไขเป็น IP ในระบบ LAN ของคุณ (เพียงตรวจสอบให้แน่ใจว่าคุณใช้ DNS ท้องถิ่นในทุกเครื่องของคุณ)

ตอนนี้คุณอาจไม่ต้องการเปิดเผยพอร์ต 22 สู่อินเทอร์เน็ตสาธารณะเพราะคุณจะได้รับการจราจรที่น่าเบื่อมากมาย ดังนั้นคุณอาจให้เราเตอร์ของคุณเปิดเผย raspi: 22 เหมือนกับพอร์ตอื่น ๆ พูด 1234 หากต้องการใช้พอร์ตเดียวกันบนเครือข่ายสาธารณะและภายในคุณสามารถเพิ่มกฎการเปลี่ยนเส้นทางพอร์ตไปยัง raspi บน Linux:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1234 -j REDIRECT --to-port 22
sudo sh -c 'iptables-save > /etc/iptables/iptables.rules'

(เปลี่ยน eth0 เป็นชื่อของอินเทอร์เฟซเครือข่ายของคุณตามที่แสดงโดยip linkหรือifconfigและ 1234 เป็นพอร์ตสาธารณะของคุณ)

ตอนนี้คุณสามารถทำได้ssh -p 1234 raspi.yourdomain.comจากทั้งสาธารณะและ LAN

คุณสามารถเพิ่มรายการใน ~ / .ssh / config บนเครื่องไคลเอนต์ของคุณเพื่อย่อให้เหลือเพียงssh raspi, ดังที่ @DopeGhoti พูดถึง

หากคุณต้องการแสดงพอร์ต SSH ของเครื่องเพิ่มเติมใน IP สาธารณะเดียวกันเพียงทำซ้ำกระบวนการด้วยชื่อ DNS อื่นและพอร์ตสาธารณะ ไชโย!


0

ต่อไปนี้เป็นคำตอบสั้น ๆ ของ Aleksi Torhamo ที่ใช้งานได้โดยใช้ curl เพื่อรับไอพีสาธารณะปัจจุบันของคุณและตรวจสอบว่ามันตรงกับไอพีสาธารณะของเซิร์ฟเวอร์ของคุณหรือไม่ (เช่นคุณอยู่ในเครือข่ายท้องถิ่นเดียวกัน)

ในการ~/.ssh/configเพิ่มของคุณ

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) == '12.345.67.89' ]]"
  User john
  HostName 192.168.2.7

Match host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]"
  User john
  HostName 12.345.67.89
  Port 1234

ผมเชื่อว่า sshจะดำเนินการตามแนวทางที่ตรงกันทั้งหมดในการสั่งซื้อดังนั้นในทฤษฎีคุณควรจะสามารถที่จะทำสิ่งที่ต้องการMatch host raspi / User john / HostName 192.168.2.7ตามมาด้วยMatch host raspi exec "[[ $(curl -s ipinfo.io/ip) != '12.345.67.89' ]]" / HostName 12.345.67.89 / Port 1234และได้รับผลเช่นเดียวกันมีเพียงหนึ่งcurlภาวนาปล่อยให้== '12.345.67.89'กรณีที่จะคิดจากความล้มเหลวที่สองของกฎMatch exec
FeRD

(คุณต้องการ Jut ต้องให้แน่ใจว่าอาร์กิวเมนต์ที่ระบุไว้ในครั้งแรกที่ทุกคนMatchเป็นอย่างใดอย่างหนึ่งที่เหมือนกันหรือยังระบุไว้ในหนึ่งวินาที - ถ้าคุณระบุไม่ได้มาตรฐานPort xxxxในครั้งแรกMatchและอยากจะใช้พอร์ตมาตรฐานในครั้งที่สองMatch, คุณจะต้องแทนที่ทับกลับอย่างชัดเจนPort 22เพื่อไม่ให้ใช้พอร์ตต่อไปxxxx)
FeRD

0

สมมติว่าเครื่องของคุณมี IP 192.168.1. * เมื่อเชื่อมต่อกับ LAN ของคุณคุณสามารถทำสิ่งนี้ได้ด้วยการกำหนดค่าต่อไปนี้~/.ssh/configเพื่อให้คุณสามารถใช้คำสั่งเดียวกัน (เพียงssh raspi) ในการเชื่อมต่อ:

Match Originalhost raspi Exec "ifconfig | grep 192\.168\.1\."
    HostName 192.168.1.2
    User john
    Port 22

Host raspi
    HostName 12.34.56.78
    User john
    Port 1234

0

วิธีแก้ปัญหานี้สันนิษฐานว่าเครือข่ายในบ้านของคุณมีเราเตอร์ตัวเดียวซึ่งฉันเชื่อว่าเป็นกรณีทั่วไป

เพิ่มของคุณ ~/.ssh/config

Match host raspi exec "test $(arp 192.168.1.1 | awk '{print $4}') = ROUTER_MAC_ADDRESS"
        Hostname 192.168.2.7
        User john

Host raspi
        Hostname 12.345.67.89
        Port 1234
        User john
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.