Gunakan dua alamat ip yang berbeda per host di SSH

23

Saya memiliki server, bernama gamma, terus-menerus beroperasi di tempat kerja. Kadang-kadang saya menghubungkannya dari di rumah, dalam hal ini saya menggunakan alamat IP publik 55.22.33.99. Terkadang, saya terhubung ketika saya sedang bekerja, dan bukannya memantulkan paket saya ke tempat yang tidak perlu, saya terhubung melalui alamat IP lokal 192.168.1.100,.

Saat ini, saya membaginya menjadi dua entri yang berbeda ~/.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

Jadi, jika saya sedang bekerja, yang harus saya ketik adalah ssh gamma-localdan saya masuk; jika saya di rumah (atau di mana pun di dunia), saya lari ssh gamma-remote.

Saat menghubungkan ke server, saya lebih suka tidak harus mengetik nama yang berbeda tergantung di mana saya berada, saya lebih suka bagian itu dilakukan secara otomatis; misalnya, dalam beberapa kasus saya memiliki skrip otomatis yang menghubungkan yang tidak tahu keberadaan saya.

Ada pertanyaan yang memecahkan masalah ini dengan menggunakan skrip Bash untuk "mencoba" menyambung ke lokal terlebih dahulu, dan jika tidak terhubung, coba sambungkan ke alamat IP jarak jauh. Ini bagus, tetapi (1) tampaknya tidak efisien (terutama karena kadang-kadang Anda harus "menunggu" koneksi ke time out karena mereka tidak selalu mengirim kesalahan segera kembali) dan (2) membutuhkan Bash dan menyeret skrip.

Apakah ada cara alternatif untuk mencapai hal ini yang tidak bergantung pada penggunaan skrip Bash, atau "pengujian" untuk melihat apakah koneksi berfungsi terlebih dahulu?

IQAndreas
sumber
Apa yang saya coba cari tahu adalah apakah seseorang dapat mengutak-atik /etc/hostsatau file konfigurasi SSH untuk mencapai ini? Atau mungkin beberapa cara "mendeteksi" LAN mana yang saat ini terhubung?
IQAndreas
Apakah Anda memiliki satu set server nama yang digunakan oleh jaringan kantor Anda?
Sree
@Sree Ah, saya melihat di mana Anda menuju dengan ini; pintar! Kami tidak menjalankan nameserver saat ini, tetapi saya pasti dapat mengubah salah satu mesin menjadi satu.
IQAndreas
@Sree Jangan ragu untuk menguraikan dan menambahkan itu sebagai jawaban yang dimulai dengan baris "Jika Anda memiliki server nama di jaringan kantor Anda ..."
IQAndreas
Lakukan itu. Jangan ragu untuk memilih / memilih :)
Sree

Jawaban:

28

Jika Anda memiliki cara untuk mengenali jaringan yang Anda gunakan maka Anda dapat menggunakan Matchkata kunci ~/.ssh/configuntuk melakukan apa yang Anda inginkan. Ini membutuhkan OpenSSH ≥6.5.

Saya menggunakan sesuatu yang mirip dengan

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

Jadi saya menggunakan pengidentifikasi dari jaringan wifi yang digunakan untuk memutuskan apakah saya di rumah untuk keperluan koneksi SSH, tetapi memeriksa alamat IP yang ditugaskan untuk komputer Anda atau hal lain yang membedakan kedua jaringan dapat digunakan juga .

Michał Politowski
sumber
+1 penggunaan cerdas Match, terima kasih! Mungkin ide yang baik untuk membungkus deteksi menjadi skrip yang keluar dengan status keluar nol atau tidak nol, karena itu akan membuatnya dapat digunakan kembali.
peterph
@ Peterph tentu saja dapat diabstraksi menjadi skrip eksternal, tapi saya hanya perlu di satu tempat sampai sekarang, jadi aturan tiga belum ditendang.
Michał Politowski
Apa yang akan terjadi jika Anda sedang bekerja, tetapi Anda sebenarnya ingin terhubung ke beberapa mesin lain? Tidakkah pernyataan exec cocok karena Anda tidak menggunakan WiFi dengan HomeESSID Anda, dan karenanya mengatur nama host menjadi 192.168.1.100?
pergi
@ hilang aku tidak mengerti pertanyaannya. Pertandingan juga pada host target.
Michał Politowski
1
@ tipografi Tidak mudah, sejauh yang saya tahu. Anda dapat mencoba menggunakan ProxyCommand nc $address ssh, tetapi kemudian mis. apakah semua perangkat memiliki kunci host yang sama? Ad jika Anda harus menetapkan variabel lingkungan, bukankah akan lebih mudah untuk memberikan alamat untuk terhubung secara langsung sebagai argumen ssh?
Michał Politowski
5

Jika Anda memiliki server nama pribadi di kantor dan jika Anda menggunakan laptop yang sama dari kantor dan rumah, Anda dapat memanfaatkan itu untuk mencapai ini:

  1. Ubah nsswitch.confdi mesin Anda untuk memeriksa DNS terlebih dahulu
  2. Buat entri DNS untuk gammadiselesaikan hingga 192.168.1.100 di DNS pribadi Anda di kantor.
  3. Buat entri di file / etc / hosts dari mesin Anda untuk menyelesaikan gammake 55.22.33.99.

Dengan cara ini, ketika Anda ssh gammadari kantor, itu akan menyelesaikan dari DNS kantor ke 192.168.1.100 dan ketika Anda terhubung dari rumah, itu akan menyelesaikan ke 55.22.33.99 dari file host Anda.

PS : Jawaban ini mengasumsikan bahwa Anda tidak ingin gamma memiliki entri DNS publik. Juga, jika Anda SSHing ke server Anda dari mesin Windows, saya pikir harus ada tempat yang setara dengan file nssswitch.conf untuk mengganti entri file hosts.

Sree
sumber
Ada - itu adalah file host. Dan ini persis bagaimana saya melakukannya - ketika di rumah domain publik saya memutuskan untuk ip lokal saya. Jawaban luar biasa - itu adalah hal pertama yang saya pikirkan juga. Yah ... hari ini, ketika saya mengaturnya beberapa tahun yang lalu saya harus banyak google untuk menemukan solusi.
mikeserv
2

Saya tidak tahu apakah mungkin untuk melakukan ini melalui ~/.ssh/configtetapi pendekatan lain akan terhubung ke satu atau yang lain berdasarkan alamat IP eksternal Anda. Karena, mungkin, ketika Anda sedang bekerja, IP Anda akan 55.22.33.NNN, Anda dapat menjalankan sesuatu seperti:

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

Pendekatan yang lebih sederhana adalah dengan menggunakan IP internal Anda. Saya tidak tahu bagaimana dua jaringan Anda diatur tetapi jika mudah untuk menentukan apakah Anda sedang bekerja atau tidak melalui IP Anda (misalnya, jika Anda memiliki IP tertentu di tempat kerja, seperti 192.168.1.12), Anda dapat melakukannya ( ubah eth0ke apa pun nama kartu jaringan Anda):

[[ $(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

Apa pun yang Anda putuskan untuk digunakan, Anda dapat menambahkannya sebagai alias ke shell Anda (tambahkan baris ini ke file inisialisasi shell Anda, ~/.bashrcjika Anda menggunakan bash):

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

Anda juga dapat menjadikannya skrip jika Anda ingin skrip lain memiliki akses ke skrip tersebut (alias .bashrctidak dibaca saat menjalankan skrip).

terdon
sumber
2

Anda tidak dapat mencapai ini ~/.ssh/configketika menggunakan alamat IP sebagai nama host. Komplikasi tambahan diperkenalkan oleh fakta, bahwa Anda tidak hanya menghubungkan ke alamat IP yang berbeda tetapi juga port yang berbeda, karena itu cukup banyak aturan dari setiap tweaker dari resolver DNS Anda.

Saya berdiri dikoreksi - Anda dapat menggunakan Match originalhost ... exec ...combo di ~/.ssh/config- lihat jawaban @ MichałPolitowski . Namun, meskipun itu akan berfungsi dengan baik untuk OpenSSH, Anda mungkin tidak perlu menemukan fungsionalitas serupa di klien SSH lainnya.

Anda dapat mengatasi masalah menggunakan pembungkus sederhana (baik fungsi shell atau skrip jika Anda perlu menggunakannya dari berbagai shell) ssh, yang akan memeriksa jaringan apa yang Anda gunakan dan menggunakan Hostentri yang sesuai . Pertanyaan besarnya adalah, bagaimana cara mendeteksi dengan andal jaringan Anda saat ini. Alamat IP lokal muncul di pikiran, tetapi tidak dapat diandalkan, karena Anda mungkin juga menghubungkan dari LAN yang menggunakan subnet yang sama dengan jaringan kerja Anda.

Jika Anda dapat memiliki port yang sama untuk jaringan lokal dan jarak jauh, Anda dapat mengedit /etc/resolv.conftergantung pada jaringan yang Anda gunakan - jelas itu harus dilakukan secara otomatis (kemungkinan besar dari skrip kait klien DHCP Anda). Atau - lebih baik - jalankan server nama lokal (seperti misalnya dnsmasq) dan berikan dengan konfigurasi yang sesuai. Itu melampaui lingkup pertanyaan ini.

Pilihan lain - jika Anda hanya perlu terhubung secara interaktif - adalah menggunakan perintah yang akan memindai ~/.ssh/config. Itu akan menghemat beberapa pengetikan (terutama jika Anda memiliki Hostentri yang cukup beragam ). Sesuatu seperti ini (untuk bashinisialisasi):

# 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

Fungsi pertama membuat daftar dari mana host selesai (biasanya itu cukup untuk menjalankan ini sekali dalam setiap shell), yang kedua melakukan penyelesaian yang sebenarnya, meskipun dengan sedikit canggung - hanya melengkapi nama host ketika itu token terakhir pada baris perintah.

Semua ini mengatakan, cara yang tepat untuk mendekati masalah ini adalah menghubungkan ke jaringan kerja melalui VPN dan dengan demikian memiliki alamat IP pekerjaan lokal yang dapat diakses seolah-olah Anda berada di kantor. Anda kemudian dapat keras-kawat alamat menjadi apa pun lapisan mana yang Anda inginkan: ~/.ssh/config, /etc/resolv.confatau (imho pilihan terbaik) nama kantor Server.

peterph
sumber
Port tidak diatur dalam batu. Saya pasti bisa mengubah port SSH lokal gammaagar sesuai dengan port jarak jauh jika itu akan membuat segalanya lebih mudah.
IQAndreas
2

Beberapa tahun yang lalu, saya menulis sebuah program untuk tujuan yang sama. Mungkin sesuai dengan kebutuhan Anda. Dengan program itu konfigurasi ssh dapat terlihat seperti ini:

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

Namun solusi lain adalah dengan menggunakan dua file konfigurasi yang berbeda untuk SSH. Anda mungkin menganggap ini sedikit kurang elegan daripada memiliki segalanya dalam satu file konfigurasi, tetapi lebih mudah untuk mempertahankannya.

Anda memilih file konfigurasi yang ingin Anda gunakan -F <configfile>.

Marcel Loose
sumber
Terima kasih. Saya suka -Fopsinya.
typelogic
0

Sebagian jawaban:

Banyak jawaban di atas dimulai dengan "jika Anda dapat mendeteksi di jaringan mana Anda berada". Untuk ini saya menggunakan skrip yang berjalan ketika antarmuka terhubung untuk memulai berbagai hal (VPN, biasanya) ketika saya terhubung ke salah satu jaringan saya yang biasa. Tekniknya adalah menggunakan ARP untuk mendapatkan alamat MAC gateway:

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
}

Dan kemudian saya memiliki tabel pencarian untuk menghubungkan jaringan ke gateway MAC. Tentu saja tabel itu dapat menampung beberapa MAC untuk jaringan yang sama (kasing tipikal adalah berbagai hotspot Wifi di situs perusahaan besar). Tabel pencarian lain digunakan untuk menentukan skrip yang akan dijalankan untuk jaringan itu.

Dalam kasus saya, skrip dijalankan menggunakan notifikasi desktop Plasma, jadi semuanya ada di userland.

xenoid
sumber