การเข้าถึง SSH ไปยังโฮสต์สำนักงานที่อยู่เบื้องหลังเราเตอร์ NAT


33

ฉันต้องการเข้าถึงพอร์ต ssh ของโฮสต์ linux ที่ทำงานจากที่บ้าน น่าเสียดายที่โฮสต์นั้นอยู่ด้านหลัง NAT เราเตอร์ ดังนั้นที่อยู่ IP จึงไม่เปิดเผยต่อสาธารณะ อย่างไรก็ตามมีการเข้าถึงไปยังโฮสต์อินเทอร์เน็ตอื่น (เซิร์ฟเวอร์) ซึ่งน่าเสียดายเพียงการเข้าถึงที่ไม่ใช่รูท หลังจากค้นหาไปสักพักฉันไม่พบวิธีแก้ไขที่เหมาะสม

การตั้งค่าต่อไปนี้:

  • Office PC (linux, root access) ที่อยู่เบื้องหลัง NAT (IP ไม่ใช่สาธารณะ) แต่การเข้าถึงอินเทอร์เน็ตเต็มรูปแบบ
  • เซิร์ฟเวอร์ PC (ลินุกซ์ไม่มีการเข้าถึงรูท) IP แบบคงที่และสาธารณะและการเข้าถึงอินเทอร์เน็ตเต็มรูปแบบ
  • Home PC (linux, root access) ที่อยู่เบื้องหลัง NAT (IP ไม่ใช่สาธารณะ) แต่ใช้อินเทอร์เน็ตได้เต็มรูปแบบ

การเชื่อมต่อที่เป็นไปได้: Office PC -> เซิร์ฟเวอร์ <- Home PC

เป็นไปไม่ได้: Office PC <-X- Server -X-> Home PC

ทั้งพีซีในบ้านและเซิร์ฟเวอร์ไม่สามารถเริ่มต้นเข้าถึงพีซี Office ได้ แต่ทั้งพีซี Office และพีซีในบ้านสามารถเริ่มต้นการเชื่อมต่อกับเซิร์ฟเวอร์ได้

อุโมงค์ SSH ย้อนกลับเป็นไปไม่ได้: ฉันลองใช้วิธีที่เรียกว่า reverse ssh-tunnel น่าเสียดายที่ต้องใช้ GatewayPorts บนเซิร์ฟเวอร์ตั้งค่าเป็น "ใช่" ใน / etc / ssh / sshd_config ซึ่งฉันไม่มีสิทธิ์เข้าถึงรูต

โดยหลักการแล้วควรเป็นไปได้:

0) บนเซิร์ฟเวอร์ฉันเริ่มโปรแกรม userspace ซึ่งฟังพอร์ต 2 พอร์ต (ขาเข้า 1, ขาออก 1)

1) บนพีซีที่ทำงานของฉันฉันเรียกใช้โปรแกรมอื่นซึ่งเปิดการเชื่อมต่อ TCP ไปยังพอร์ตขาออกบนเซิร์ฟเวอร์

2) จากบ้านฉันเชื่อมต่อกับพอร์ตขาเข้าของเซิร์ฟเวอร์

ควรมีโซลูชันมาตรฐานสำหรับสิ่งนี้

อะไรคือวิธีแก้ปัญหาที่เร็วและสะอาดที่สุดในการแก้ไขปัญหานี้?

ตรงไปตรงมา


1
พีซีที่ทำงานสามารถเชื่อมต่อกับการตั้งค่าอุโมงค์ ssh ได้หรือไม่ en.gentoo-wiki.com/wiki/Autossh

คุณสามารถใช้ FileZilla ด้วย sftp และการส่งต่อพอร์ต ตรวจสอบ: superuser.com/a/1286681/141314
Noam Manos

คำตอบ:


31
youatwork@officepc$ autossh -R 12345:localhost:22 notroot@serverpc

ต่อมา:

you@homepc$ autossh -L 23456:localhost:12345 notroot@serverpc

you@homepc$ ssh youatwork@localhost -p 23456

สิ่งที่คุณสามารถทำได้คือ: ในขั้นตอนที่ 1 ส่งต่อพอร์ตระยะไกลจากพีซีสำนักงานไปยังเซิร์ฟเวอร์ ( 12345ใช้เป็นตัวอย่างพอร์ตใดก็ได้> 1024 ควรทำ) ตอนนี้เชื่อมต่อกับ 12345 บนเซิร์ฟเวอร์ควรเชื่อมต่อคุณกับพอร์ต 22 บน officepc

ในขั้นตอนที่ 2 ส่งต่อพอร์ต 23456 จากเครื่องที่บ้านของคุณไปยัง 12345 บนเซิร์ฟเวอร์ (ซึ่งเครื่องจะถูกส่งต่อไปยัง officepc: 22 ตามที่ตั้งค่าในขั้นตอนที่ 1)

ในขั้นตอนที่ 3 คุณเชื่อมต่อกับพอร์ตท้องถิ่น 23456 กับการเข้าสู่ระบบสำนักงานเครื่องคอมพิวเตอร์ของคุณ สิ่งนี้จะถูกส่งต่อโดยขั้นตอนที่ 2 ถึงพอร์ต 12345 บนเซิร์ฟเวอร์ของคุณและโดยขั้นตอนที่ 1 ไปยังพีซีในสำนักงานของคุณ

โปรดทราบว่าฉันกำลังใช้ autossh สำหรับการส่งต่อเนื่องจากเป็น ssh wrapper ที่เชื่อมต่ออุโมงค์อีกครั้งโดยอัตโนมัติหากมีการตัดการเชื่อมต่อ อย่างไรก็ตาม ssh ปกติจะทำงานได้ดีตราบใดที่การเชื่อมต่อไม่ลดลง

มีช่องโหว่ที่อาจเกิดขึ้นได้: ทุกคนที่สามารถเชื่อมต่อกับโฮสต์ในพื้นที่: 12345 บนเซิร์ฟเวอร์พีซีสามารถเชื่อมต่อกับ officepc: 22 และลองแฮ็คข้อมูล (โปรดทราบว่าหากคุณใช้เซิร์ฟเวอร์ SSH คุณควรรักษาความปลอดภัยไว้เหนือการป้องกันขั้นพื้นฐานที่เปิดอยู่ตามค่าเริ่มต้นฉันแนะนำอย่างน้อยปิดการใช้งานการเข้าสู่ระบบรูทและการปิดใช้งานการตรวจสอบรหัสผ่าน - ดูเช่นนี้ )

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

homepc:
  outgoing ssh to serverpc:22
  listening localhost:23456 forwarded through ssh tunnel
serverpc:
  listening ssh at *:22
  incoming localhost ssh tunnel (from homepc) forwarded to localhost:12345
  listening localhost ssh tunnel (from officepc) forwarded from localhost:12345
officepc:
  outgoing ssh to serverpc:22
  incoming localhost through ssh tunnel (from serverpc) forwarded to localhost:22

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

อย่างไรก็ตามมีคำสั่งAllowTcpForwarding: หากเป็นnoเช่นนั้นการตั้งค่านี้จะล้มเหลวเนื่องจากไม่อนุญาตให้ส่งต่อเลยแม้แต่ในส่วนต่อประสานวนรอบ

คำเตือน :

  • หากใช้ autossh และ ssh ล่าสุดคุณอาจต้องการใช้ ssh ServerAliveIntervalและServerAliveCountMaxทำให้อุโมงค์ทำงาน Autossh มีการตรวจสอบในตัว แต่ดูเหมือนจะมีปัญหาบางอย่างเกี่ยวกับ Fedora -M0ปิดใช้งานนั้นและ-oServerAliveInterval=20 -oServerAliveCountMax=3ตรวจสอบว่าการเชื่อมต่อหมดหรือไม่ - ลองทุก ๆ 20 วินาทีหากเชื่อมต่อไม่ถึง 3x ในหนึ่งแถวให้หยุด ssh (และ autossh สร้างใหม่):

    autossh -M0 -R 12345:localhost:22 -oServerAliveInterval=20 -oServerAliveCountMax=3 notroot@serverpc
    
    autossh -M0 -L 23456:localhost:12345 -oServerAliveInterval=20 -oServerAliveCountMax=3 notroot@serverpc
    
  • อาจเป็นประโยชน์ในการรีสตาร์ทอุโมงค์ ssh หากการส่งต่อล้มเหลวโดยใช้-oExitOnForwardFailure=yes- หากพอร์ตถูกผูกไว้แล้วคุณอาจได้รับการเชื่อมต่อ SSH ที่ใช้งานได้ แต่ไม่มีช่องสัญญาณที่ส่งต่อ

  • แนะนำให้ใช้~/.ssh/configสำหรับตัวเลือก (และพอร์ต) มิฉะนั้นบรรทัดคำสั่งจะได้รับรายละเอียดมากเกินไป ตัวอย่างเช่น:

    Host fwdserverpc
        Hostname serverpc
        User notroot
        ServerAliveInterval 20
        ServerAliveCountMax 3
        ExitOnForwardFailure yes
        LocalForward 23456 localhost:12345
    

จากนั้นคุณสามารถใช้ชื่อแทนเซิร์ฟเวอร์ได้:

    autossh -M0 fwdserverpc

ฉันเชื่อว่าวิธีนี้คุณคิดว่าเรียกว่า "reverse ssh-tunnel" น่าเสียดายที่ต้องมี GatewayPorts บนเซิร์ฟเวอร์ตั้งค่าเป็น "ใช่" ใน / etc / ssh / sshd_config เซิร์ฟเวอร์นี้ไม่มีพอร์ตเกตเวย์เปิดใช้งานและฉันไม่สามารถเข้าถึงรูทได้

3
@ Frank: จริง ๆ แล้วฉันไม่คิดอย่างนั้น: GatewayPorts noจำกัด พอร์ตที่เปิดให้เข้าถึงได้เฉพาะบนอินเตอร์เฟสลูปแบ็ค โปรดทราบว่าในขั้นตอนที่ 2 คุณกำลังส่งต่ออินเทอร์เฟซแบบวนรอบ (ในความเป็นจริงทั้งสองส่งต่อเป็น "localhost เท่านั้น") ดังนั้นสิ่งนี้อาจใช้งานAllowTcpForwarding noได้
Piskvor

3
@ Frank: ใช่ยืนยันแล้ว ใช้งานได้กับGatewayPorts no; แก้ไขคำตอบ โปรดทราบว่ามีคำสั่งอื่น ๆ (เช่นPermitOpenและAllowTcpForwarding) ที่สามารถหยุดการตั้งค่านี้: manpagez.com/man/5/sshd_config
Piskvor

1
คำตอบที่ยอดเยี่ยม! มันใช้งานได้คุณบันทึกวันหยุดสุดสัปดาห์ของฉัน! ขอบคุณมาก!!

1
รุ่น autossh ของฉัน (Fedora Core) ไม่สามารถเรียกใช้จากเทอร์มินัลโดยไม่มี -M ฉันยังเชื่อมโยงกับบุคคลอื่นที่มีประสบการณ์นั้น คุณถูกต้องว่าในคู่มือจะมีการทำเครื่องหมายเป็นอาร์กิวเมนต์ตัวเลือก ดีถ้ามันใช้ได้กับหลาย ๆ คนน่าเสียดายสำหรับทุกคน
Yaroslav Nikitenko

4

หากคุณสามารถ ssh ไปยังเซิร์ฟเวอร์ภายในจากที่บ้านและจากเซิร์ฟเวอร์ภายในไปยังเครื่อง Linux ในสำนักงานของคุณจากที่บ้านคุณสามารถใช้ ssh ProxyCommandเพื่อตีกลับอย่างเงียบ ๆ ผ่านเซิร์ฟเวอร์ไปยังเครื่องภายในผ่านnc(netcat)

# ~/.ssh/config on your home machine:
Host internalpc 
   ForwardAgent yes 
   ProxyCommand ssh user@server.example.com exec nc internal.pc.example.com %p

จากนั้นคุณเพียงแค่ssh user@internalpcและคุณจะถูกส่งต่ออย่างเงียบ ๆ ผ่านเครื่องเซิร์ฟเวอร์ไม่ต้องเปิดพอร์ตหรืออุโมงค์ที่ปลายทั้งสองข้าง


1
ขอบคุณสำหรับคำตอบ. น่าเสียดายที่ Home PC และเซิร์ฟเวอร์ไม่สามารถเริ่มการเข้าถึง Office PC ได้ แต่ทั้ง Office PC และ Home PC สามารถเริ่มต้นการเชื่อมต่อกับเซิร์ฟเวอร์

4

ติดตั้ง Robo-TiTO ในคอมพิวเตอร์ที่คุณต้องการเข้าถึง SSH จากระยะไกล

  • สิ่งนี้จะช่วยให้คุณเข้าถึง SSH ที่ใช้จาก Google Talk Client Apps ได้ทุกที่
  • ไม่จำเป็นต้องมีที่อยู่ IP สาธารณะหรือการตั้งค่าพิเศษ
  • ฟรีและโอเพ่นซอร์สไม่ต้องจ่ายค่าบริการแอปพลิเคชันอีกต่อไป
  • ไม่จำเป็นต้องเปิดพอร์ต SSH (ทำให้คอมพิวเตอร์ของคุณปลอดภัย)
  • ไม่จำเป็นต้องเปิดการขุดอุโมงค์ใด ๆ (เช่น VPN หรืออะไรทำนองนั้น)

คำแนะนำการติดตั้งต่อไปนี้ล้าสมัยเนื่องจากไซต์ได้ย้ายไปแล้ว URL ใหม่คือhttps://github.com/formigarafa/robotito

ฉันสร้างสคริปต์ (ทดสอบบน Raspbian OS ของฉันใน Raspberry Pi) เพื่อให้คุณสามารถติดตั้ง Robo-TiTO ได้อย่างง่ายดายบน Raspberry Pi, Debian หรือ Ubuntu Box (การกระจายแพคเกจ Debian) นี่คือขั้นตอนในการรับกล่อง Linux ของคุณจากระยะไกล:

  1. เปิดคำสั่ง Shell หรือคุณสามารถเรียกมันว่า Terminal ไปที่โฟลเดอร์บ้านของคุณดาวน์โหลดสคริปต์ตัวติดตั้งโดยคำสั่ง

    $ wget https://opengateway.googlecode.com/files/robotito
    
  2. หลังจากนั้นเรียกใช้สคริปต์โดยป้อนคำสั่ง:

    $ sudo ./robotito
    
  3. และจากนั้นคุณสามารถแก้ไขไฟล์credentials.rbจากโฟลเดอร์การตั้งค่าของโบตีโต้ใช้บัญชี GTalk ของคุณและบันทึกโดยการกดCtrl+ และX Yค่าเริ่มต้นคือการใช้โปรแกรมแก้ไขนาโน

  4. รัน Robo-TiTO จากโฟลเดอร์ Robo-TiTO ตามคำสั่ง

    $ cd robotito
    $ ./jabbershd start
    
  5. หลังจากนี้คุณสามารถใช้ SSH ได้จากไคลเอนต์ Google Talk ใด ๆ อย่าลืมเพิ่มบัญชี GTalk Robo-TiTO ไปยังบัญชี Google Talk ของคุณและทดสอบด้วยการแชทกันก่อนใช้งานบัญชี


5
ฉันมีความร้ายแรงปัญหากับ "ไม่จำเป็นต้องเปิดพอร์ต SSH (ให้คอมพิวเตอร์ของคุณประหยัด )" - บอเปลือก-over-ส่งเสียงเจี๊ยวจ๊าวที่คุณเสนอเป็นหลักประกันกับคำพูดCLIENT_PASSPHRASE = "logmein"ในเท็กซ์ นั่นคือการรักษาความปลอดภัยที่ไม่มีศูนย์ - คุณกำลังสร้างหลุมขนาดรถบรรทุกเพื่อให้ทุกคนเข้ามา ตรงกันข้ามกับการรับรองความถูกต้องของคีย์สาธารณะ SSH: ฉันกำลังตรวจสอบผ่านช่องทางที่ปลอดภัยโดยใช้ข้อมูลรับรองที่ไม่เคยข้ามสาย ใครเป็นผู้ดูแลคอมพิวเตอร์ให้ปลอดภัย
Piskvor

@Piskvor, robotito จะเรียกใช้คำสั่งจากผู้ติดต่อที่อยู่ในรายการที่อนุญาตพิเศษเท่านั้น github.com/formigarafa/robotito/blob/master/config/…
formigarafa

ฉันไม่เคยพบปัญหาใด ๆ เนื่องจากการตรวจสอบสิทธิ์ตามรายการที่อนุญาต หากฉันไม่ผิดการถ่ายโอนข้อความจะถูกเข้ารหัสเมื่อใช้กับ GTalk ไม่ทางใดก็ทางหนึ่งฉันเปลี่ยนมันเมื่อเร็ว ๆ นี้และตอนนี้มันใช้รหัสผ่านครั้งเดียวจากเครื่องมือเช่น Google Authenticator หรือคล้ายกันเพื่ออนุญาตการเข้าถึง
formigarafa

1
@formigarafa: (1) หากคุณมีส่วนร่วมหรือมีส่วนร่วมในการพัฒนาผลิตภัณฑ์นี้คุณต้องพูดอย่างชัดเจน การใช้ชื่อเดียวกันนั้นไม่เพียงพอ คนส่วนใหญ่จะไม่สังเกตเห็นว่า (คุณอาจพูดถึงมันในโปรไฟล์ของคุณ ) (2) เมื่อคุณแก้ไขโพสต์คุณควรแก้ไขให้มากที่สุด ตัวอย่างเช่นพยายามสะกดคำว่า "ฉัน" และหากลิงก์ลงไปอย่าเพิ่งระบุว่ามันเป็นลิงก์ที่ตายแล้ว ใส่ URL ใหม่เข้ามาโพสต์ ผู้คนไม่ควรเจาะผ่านความคิดเห็นเพื่อค้นหาข้อมูลที่ถูกต้อง
G-Man กล่าวว่า 'Reinstate Monica'

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

3

โซลูชันของ Piskvor ทำงานได้ดี อย่างไรก็ตามมันทำให้เทอร์มินัลห้อยอยู่เปิดด้วยการล็อกอินเชลล์แขวน ไม่เท่ห์มาก

ฉันมักจะใช้สคริปต์เล็ก ๆ นี้ที่ฉันเขียนเพื่อเชื่อมต่อกับเซิร์ฟเวอร์และให้มันเชื่อมต่อโดยใช้มันใน cron:

#!/bin/bash
TARGET_HOST=${1:-myserver.example.com}
TARGET_PORT=${2:-7777}
TUNNEL_PORT=${3:-22}
T_USER="odin"

#Check that we have an active connection to the remote system
ACTIVE_PROCESS=`ps -ef | \
    grep "ssh $TARGET_HOST -l $T_USER -R $TARGET_PORT:127.0.0.1:$TUNNEL_PORT" | \
    grep -v grep | \
    wc -l`
if [ $ACTIVE_PROCESS -lt 1 ]; then
    echo "`date` : establishing connection to $TARGET_HOST on port $TARGET_PORT"
    screen -m -d ssh $TARGET_HOST -l $T_USER -R $TARGET_PORT:127.0.0.1:$TUNNEL_PORT > /dev/null
fi

ฉันพนันได้ว่าเราสามารถแก้ไขวิธีแก้ปัญหาของ Piskvor โดยใช้ autossh ที่สง่างามกว่าข้างหน้าจอที่แยกออกมาหรือใช้อาร์กิวเมนต์ -NT ssh เพื่อทำการเชื่อมต่อในพื้นหลัง


ขอบคุณสำหรับคำชมเชย :) สำหรับกรณีการใช้งานของฉันฉันจำเป็นต้องเข้าถึงเชลล์เป็นประจำรวมถึงการส่งต่อ; นอกจากนี้ฉันได้พยายามแสดงกรณีที่น้อยที่สุดที่นี่ (มันเป็นไปได้ที่จะทำให้คำสั่งข้างต้นเป็นสองคำสั่งโดยง่ายด้วยการข้ามโฮสต์ SSH แบบโปร่งใส แต่นั่นจะต้องมีการกำหนดค่าเพิ่มเติมในhomepcคอมพิวเตอร์)
Piskvor

2

สำหรับผมแล้วมันเสียงเช่นแทนที่จะ SSH ที่คุณควรลอง VPN A: ชนิดที่ทำงานโดยใช้เซิร์ฟเวอร์ที่อยู่ข้างนอกผ่านพร็อกซี่เช่นHamachi มีซอฟต์แวร์ฟรีอื่น ๆ เช่นนี้ แต่ Hamachi เป็นที่โปรดปรานของฉัน


1
ตอนนี้5.0.0.0/8เครือข่ายมีที่อยู่ IPv4 สาธารณะที่กำหนดไว้จริงแล้ว Hamachi ก็มีปัญหา (ถ้า Hamachi กำลังทำงานอยู่คุณจะไม่สามารถเข้าถึงอินเทอร์เน็ตที่เป็นแบบสุ่มได้) นอกจากนี้ Hamachi ไม่ใช้งานฟรีอีกต่อไป
Piskvor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.