ใช้ที่อยู่ IP ที่แตกต่างกันสองรายการต่อโฮสต์ใน SSH


23

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

ในขณะนี้ฉันให้พวกเขาแยกออกเป็นสองรายการที่แตกต่างกัน ~/.ssh/conf

Host gamma-local
        HostName 192.168.1.100
        Port 22
        User andreas

Host gamma-remote
        HostName 55.22.33.99
        Port 12345
        User andreas

ดังนั้นถ้าฉันอยู่ที่ทำงานสิ่งที่ฉันต้องทำก็คือssh gamma-localฉันอยู่ข้างใน; หากฉันที่บ้าน (หรือที่อื่นใดในโลก) ssh gamma-remoteผมทำงาน

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

มีคำถามที่แก้ปัญหานี้ได้โดยใช้สคริปต์ Bashเพื่อ "ลอง" เพื่อเชื่อมต่อกับโลคัลก่อนและหากไม่ได้เชื่อมต่อให้ลองเชื่อมต่อกับที่อยู่ IP ระยะไกล นี่เป็นสิ่งที่ดี แต่ (1) ดูเหมือนไม่มีประสิทธิภาพ (โดยเฉพาะอย่างยิ่งเนื่องจากบางครั้งคุณต้อง "รอ" เพื่อให้การเชื่อมต่อหมดเวลาเนื่องจากไม่ได้ส่งข้อผิดพลาดกลับมาทันที) และ (2) ต้องใช้ Bash และ lugging รอบสคริปต์

มีวิธีอื่นในการทำสิ่งนี้โดยไม่พึ่งพาการใช้สคริปต์ Bash หรือ "ทดสอบ" เพื่อดูว่าการเชื่อมต่อใช้งานได้หรือไม่


สิ่งที่ฉันพยายามจะหาคือถ้าใครสามารถเล่นกับ/etc/hostsไฟล์ SSH หรือเพื่อให้บรรลุนี้ หรืออาจเป็นวิธีการ "ตรวจจับ" LAN ที่คุณเชื่อมต่ออยู่ในปัจจุบัน?
IQAndreas

คุณมีเนมเซิร์ฟเวอร์อีกชุดหนึ่งที่ใช้โดยเครือข่ายสำนักงานของคุณหรือไม่?
Sree

@Sree Ah ฉันเห็นว่าคุณกำลังจะไปที่ไหน ฉลาด! เราไม่ได้ใช้ nameserver ในขณะนี้ แต่ฉันสามารถแปลงหนึ่งในเครื่องเป็นหนึ่งเดียวได้
IQAndreas

@Sree รู้สึกอิสระที่จะอธิบายอย่างละเอียดและเพิ่มเติมว่าเป็นคำตอบที่ขึ้นต้นด้วยบรรทัด"หากคุณมีเนมเซิร์ฟเวอร์ในเครือข่ายสำนักงานของคุณ ... "
IQAndreas

ทำอย่างนั้น รู้สึกอิสระที่จะขึ้น / ลงคะแนนเสียง :)
ซรี

คำตอบ:


28

หากคุณมีวิธีที่จะจดจำเครือข่ายที่คุณใช้อยู่คุณสามารถใช้Matchคำหลัก~/.ssh/configเพื่อทำสิ่งที่คุณต้องการ สิ่งนี้ต้องใช้ OpenSSH ≥6.5

ฉันใช้สิ่งที่คล้ายกับ

Match originalhost gamma exec "[ x$(/sbin/iwgetid --scheme) != xMyHomeESSID ]"
  HostName 192.168.1.100
  Port 22

Host gamma
  User andreas
  Port 12345
  HostName 55.22.33.99

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


+1 ใช้อย่างชาญฉลาดMatchขอบคุณ! อาจเป็นความคิดที่ดีที่จะห่อการตรวจจับลงในสคริปต์ที่ออกด้วยสถานะการออกจากศูนย์หรือไม่เป็นศูนย์เนื่องจากจะทำให้สามารถใช้ซ้ำได้
เตอร์

@ peterph มันอาจเป็นนามธรรมไปยังสคริปต์ภายนอก แต่ฉันต้องการเพียงที่เดียวจนถึงตอนนี้ดังนั้นกฎของสามยังไม่ได้เตะ
Michał Politowski

จะเกิดอะไรขึ้นถ้าคุณทำงาน แต่คุณต้องการเชื่อมต่อกับเครื่องอื่นหรือไม่ คำสั่ง exec จะไม่ตรงกันเนื่องจากคุณไม่ได้ใช้ WiFi กับ HomeESSID ของคุณและตั้งค่าชื่อโฮสต์เป็น 192.168.1.100 หรือไม่
ไปแล้ว

@gone ฉันไม่เข้าใจคำถาม การแข่งขันยังอยู่ในพื้นที่เป้าหมาย
Michał Politowski

1
@typelogic ไม่ง่ายเท่าที่ฉันรู้ คุณสามารถลองใช้ProxyCommand nc $address sshแต่จากนั้นเช่น อุปกรณ์ทั้งหมดมีรหัสโฮสต์เดียวกันหรือไม่ โฆษณาถ้าคุณมีการตั้งค่าตัวแปรสภาพแวดล้อมต่อไปจะไม่ได้ง่ายขึ้นเพียงเพื่อให้อยู่ในการเชื่อมต่อโดยตรงเป็นอาร์กิวเมนต์ไปยังssh?
Michał Politowski

5

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

  1. ปรับเปลี่ยนของคุณnsswitch.confในเครื่องของคุณเพื่อตรวจสอบใน DNS ก่อน
  2. สร้างรายการ DNS สำหรับgammaเพื่อแก้ไขเป็น 192.168.1.100 ใน DNS ส่วนตัวของคุณที่สำนักงาน
  3. สร้างรายการในไฟล์ / etc / hosts ของเครื่องของคุณเพื่อแก้ไขgammaเป็น 55.22.33.99

ด้วยวิธีนี้เมื่อคุณssh gammaออกจากสำนักงานมันจะแก้ไขจาก DNS ของสำนักงานไปที่ 192.168.1.100 และเมื่อคุณเชื่อมต่อจากที่บ้านมันจะแก้ไขเป็น 55.22.33.99 จากไฟล์โฮสต์ของคุณ

PS : คำตอบนี้อนุมานว่าคุณไม่ต้องการให้แกมม่ามีรายการ DNS สาธารณะ นอกจากนี้ถ้าคุณกำลัง SSHing ไปยังเซิร์ฟเวอร์ของคุณจากเครื่อง Windows ฉันคิดว่าควรมีบางสถานที่เทียบเท่ากับไฟล์ nssswitch.conf เพื่อแทนที่รายการโฮสต์ไฟล์


มี - มันเป็นไฟล์โฮสต์ และนี่คือวิธีที่ฉันทำ - เมื่ออยู่ที่บ้านโดเมนสาธารณะของฉันจะเปลี่ยนเป็น IP ท้องถิ่นของฉัน คำตอบที่ยอดเยี่ยม - มันเป็นสิ่งแรกที่ฉันคิดด้วย อืม ... วันนี้นั่นคือเมื่อฉันตั้งค่าสองสามปีที่ผ่านมาฉันต้อง google มากเพื่อหาทางออก
mikeserv

2

ฉันไม่ทราบว่าเป็นไปได้หรือไม่ที่จะทำเช่นนี้~/.ssh/configแต่อีกวิธีหนึ่งคือการเชื่อมต่อกับวิธีการอื่นโดยอ้างอิงจากที่อยู่ IP ภายนอกของคุณ ตั้งแต่สมมุติว่าเมื่อคุณทำงาน IP ของคุณจะเป็น55.22.33.NNNเช่นนั้นคุณสามารถเรียกใช้สิ่งต่อไปนี้:

[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

วิธีที่ง่ายกว่าคือใช้ IP ภายในของคุณ ฉันไม่ทราบวิธีการตั้งค่าเครือข่ายทั้งสองของคุณ แต่ถ้าเป็นการง่ายที่จะตรวจสอบว่าคุณทำงานหรือไม่ผ่าน IP ของคุณ (ตัวอย่างเช่นหากคุณมี IP เฉพาะที่ทำงานเช่น192.168.1.12) คุณสามารถทำได้ ( เปลี่ยนeth0เป็นชื่อการ์ดเครือข่ายของคุณ):

[[ $(ip address show dev eth0 | grep -Po 'inet \K[\d.]+') = '192.168.1.12' ]] && 
    ssh 192.168.1.100 ||
    ssh -p 12345 55.22.33.99

ไม่ว่าคุณจะเลือกใช้แบบไหนคุณสามารถเพิ่มมันเป็นนามแฝงในเชลล์ของคุณ (เพิ่มบรรทัดนี้ในไฟล์เริ่มต้นของเชลล์~/.bashrcหากคุณใช้bash):

alias gamma="[[ $(wget -qO - http://wtfismyip.com/text) =~ ^'55.22.33.' ]] && ssh 192.168.1.100 || ssh -p 12345 55.22.33.99

คุณสามารถทำให้เป็นสคริปต์ได้หากคุณต้องการให้สคริปต์อื่นสามารถเข้าถึงได้ ( .bashrcไม่สามารถใช้นามแฝงจากเมื่อเรียกใช้สคริปต์)


2

คุณไม่สามารถทำสิ่งนี้ได้~/.ssh/configเมื่อใช้ที่อยู่ IP เป็นชื่อโฮสต์ ความซับซ้อนเพิ่มเติมนั้นได้รับการแนะนำโดยข้อเท็จจริงที่ว่าคุณไม่เพียง แต่เชื่อมต่อกับที่อยู่ IP ที่แตกต่างกัน แต่ยังมีพอร์ตที่ต่างกันด้วย

ฉันยืนแก้ไข - คุณสามารถใช้Match originalhost ... exec ...คำสั่งผสมใน~/.ssh/config- ดู@ คำตอบของMichałPolitowski อย่างไรก็ตามแม้ว่ามันจะทำงานได้อย่างสมบูรณ์แบบสำหรับ OpenSSH แต่คุณอาจไม่พบฟังก์ชันการทำงานที่คล้ายกันในไคลเอนต์ SSH อื่น ๆ

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

หากคุณสามารถมีพอร์ตเดียวกันสำหรับทั้งเครือข่ายท้องถิ่นและเครือข่ายระยะไกลคุณสามารถแก้ไขของคุณ/etc/resolv.confขึ้นอยู่กับเครือข่ายที่คุณเปิดอยู่ - เห็นได้ชัดว่ามันจะต้องทำโดยอัตโนมัติ หรือ - ดีกว่า - รันเซิร์ฟเวอร์ชื่อโลคัล (เช่นตัวอย่างdnsmasq) และจัดหาด้วยการกำหนดค่าที่เหมาะสม มันเกินกว่าขอบเขตของคำถามนี้

อีกตัวเลือกหนึ่ง - ถ้าคุณต้องการเพียงที่จะเชื่อมต่อการโต้ตอบ - ~/.ssh/configคือการใช้เสร็จสิ้นคำสั่งที่จะสแกน ที่จะช่วยให้คุณพิมพ์บางอย่าง (โดยเฉพาะถ้าคุณมีHostรายการที่แตกต่างกันพอ) บางสิ่งเช่นนี้ (สำหรับการbashเริ่มต้น):

# complete session names for ssh
declare -g _ssh_complete_hostlist 2> /dev/null
function _ssh_complete_init () {
    _ssh_complete_hostlist=$( \
        sed -nr '/^\s*Host\s*=/{s/^[^=]+= *//;s/ /\n/g;p}' ~/.ssh/config \
        | sort )
}
_ssh_complete_init

function _ssh_complete () {
    local match=${COMP_WORDS[${COMP_CWORD}]}
    local hosts=
    local default=
    for h in $_ssh_complete_hostlist; do
        if [[ $h =~ ^$match ]]; then
            hosts="$hosts $h"
        fi
    done
    if ! (( ${COMP_CWORD} == ${#COMP_WORDS[@]}-1 )); then
        default=$( compgen -f ${COMP_WORDS[${COMP_CWORD}]} )
    fi
    COMPREPLY=($hosts $default)
}
complete -F _ssh_complete ssh

ฟังก์ชั่นแรกสร้างรายการที่โฮสต์เสร็จสมบูรณ์ (โดยปกติแล้วจะเพียงพอที่จะเรียกใช้งานนี้หนึ่งครั้งในทุกเชลล์) ส่วนที่สองทำเสร็จจริงแม้ว่าในลักษณะที่ค่อนข้างงุ่มง่าม - มันเสร็จสมบูรณ์เพียงชื่อโฮสต์เมื่อมันเป็น โทเค็นสุดท้ายบนบรรทัดคำสั่ง

ทั้งหมดนี้กล่าวว่าวิธีที่ถูกต้องในการแก้ไขปัญหานี้คือการเชื่อมต่อเข้ากับเครือข่ายงานผ่าน VPN และทำให้ที่อยู่ IP ของที่ทำงานในท้องถิ่นสามารถเข้าถึงได้ราวกับว่าคุณอยู่ในสำนักงาน จากนั้นคุณสามารถยากลวดที่อยู่แล้วแต่จำนวนใดเป็นสิ่งที่ชั้นที่คุณต้องการ: ~/.ssh/config, /etc/resolv.confหรือ imho (เลือกที่ดีที่สุด) เซิร์ฟเวอร์ชื่อสำนักงาน


พอร์ตที่ไม่ได้ตั้งอยู่ในหิน แน่นอนฉันสามารถเปลี่ยนพอร์ต SSH ท้องถิ่นของgammaเพื่อจับคู่พอร์ตระยะไกลถ้ามันจะทำให้สิ่งต่าง ๆ ง่ายขึ้น
IQAndreas

2

เมื่อหลายปีก่อนฉันเขียนโปรแกรมเพื่อจุดประสงค์เดียวกัน มันอาจตอบสนองความต้องการของคุณ ด้วยโปรแกรมนั้นการกำหนดค่า ssh อาจมีลักษณะเช่นนี้:

Host gamma
    ProxyCommand ssh-multipath-proxy 192.168.1.100:22 55.22.33.99:12345
    User andreas

1

อีกวิธีหนึ่งคือใช้ไฟล์ config สองไฟล์สำหรับ SSH คุณอาจจะคิดว่ามันน้อยกว่าการมีทุกอย่างในไฟล์ปรับแต่ง แต่มันง่ายกว่าที่จะดูแลรักษา

คุณสามารถเลือกไฟล์ config -F <configfile>ที่คุณต้องการที่จะใช้กับ


ขอบคุณ ฉันชอบ-Fตัวเลือก
typelogic

0

คำตอบบางส่วน:

คำตอบมากมายด้านบนเริ่มต้นด้วย "ถ้าคุณสามารถตรวจสอบเครือข่ายที่คุณเปิด" สำหรับเรื่องนี้ฉันใช้สคริปต์ที่ทำงานเมื่อเชื่อมต่ออินเทอร์เฟซเพื่อเริ่มสิ่งต่าง ๆ (VPNs ปกติ) เมื่อฉันเชื่อมต่อกับหนึ่งในเครือข่ายปกติของฉัน เทคนิคคือการใช้ ARP เพื่อรับที่อยู่ MAC ของเกตเวย์:

function identifyConnection {
    gatewayIP=$(route -n | grep -e '^0\.0\.0\.0' | tr -s ' ' | cut -d ' ' -f 2)

    if [[ ! -z "$gatewayIP" ]]
    then
        # Identify the gateway by its MAC (uniqueness...)
        log "Gateway IP address=$gatewayIP"
        log "Obtaining corresponding gateway MAC address"
        gatewayData=($(arp -n $gatewayIP | grep -e $gatewayIP | tr -s ' '))
        if [[ "${gatewayData[1]}" == "(incomplete)" ]]
        then
            log "Status of gateway $gatewayIP "incomplete""
            echo ""
        elif [[ "${gatewayData[2]}" == "--" ]]
        then 
            log "No MAC address found for $gatewayIP"
            echo ""
        else
            log "Gateway MAC address=[${gatewayData[2]}]"
            echo "${gatewayData[2]}"
        fi
    fi
}

จากนั้นฉันก็มีตารางค้นหาเพื่อเชื่อมโยงเครือข่ายกับเกตเวย์ MAC แน่นอนว่าตารางสามารถเก็บ MAC ได้หลายเครื่องสำหรับเครือข่ายเดียวกัน (กรณีทั่วไปคือฮอตสปอต Wifi ต่างๆในเว็บไซต์องค์กรขนาดใหญ่) ใช้ตารางการค้นหาอื่นเพื่อกำหนดสคริปต์ให้เรียกใช้สำหรับเครือข่ายนั้น

ในกรณีของฉันสคริปต์จะทำงานโดยใช้การแจ้งเตือนพลาสมาเดสก์ท็อปดังนั้นทุกอย่างอยู่ใน userland

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