ProxyCommand के माध्यम से SSH की गति में बहुत सुधार हुआ - लेकिन क्यों?


14

टीएल; डीआर संस्करण

इस ASCII कलाकारों या इस वीडियो को देखें - फिर किसी भी कारण से आएँ कि ऐसा क्यों हो रहा है। पाठ विवरण जो अधिक संदर्भ प्रदान करता है।

सेटअप का विवरण

  • मशीन 1 एक आर्क लिनक्स लैपटॉप है, जिस पर sshस्पैन किया जाता है, जो एक आर्मबियन-रनिंग एसबीसी (ऑरेंज पीआई ज़ीरो) से जुड़ता है।
  • SBC स्वयं ईथरनेट के माध्यम से DSL राउटर से जुड़ा है, और इसमें 192.168.1.150 का IP है
  • लैपटॉप एक आधिकारिक रास्पबेरी पीआई वाईफाई डोंगल का उपयोग करके वाईफाई पर राउटर से जुड़ा हुआ है।
  • ईथरनेट के माध्यम से DSL राउटर से जुड़ा एक और लैपटॉप (मशीन 2) भी है।

टोपोलॉजी

Iperf3 के साथ लिंक को बेंचमार्क करना

जब बेंचमार्क किया जाता है iperf3, तो लैपटॉप और एसबीसी के बीच का लिंक सैद्धांतिक 56 एमबीटी / सेकंड से कम है - जैसा कि अपेक्षित है, क्योंकि यह बहुत "भीड़ 2.4GHz" (अपार्टमेंट बिल्डिंग) के भीतर एक वाईफाई कनेक्शन है ।

विशेष रूप से: iperf3 -sएसबीसी पर चलने के बाद , लैपटॉप पर निम्नलिखित कमांड निष्पादित होते हैं:

# iperf3 -c 192.168.1.150
Connecting to host 192.168.1.150, port 5201
[  5] local 192.168.1.89 port 57954 connected to 192.168.1.150 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  2.99 MBytes  25.1 Mbits/sec    0    112 KBytes       
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  28.0 MBytes  23.5 Mbits/sec    5             sender
[  5]   0.00-10.00  sec  27.8 MBytes  23.4 Mbits/sec                  receiver

iperf Done.

# iperf3 -c 192.168.1.150 -R
Connecting to host 192.168.1.150, port 5201
Reverse mode, remote host 192.168.1.150 is sending
[  5] local 192.168.1.89 port 57960 connected to 192.168.1.150 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  3.43 MBytes  28.7 Mbits/sec                  
...                
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  39.2 MBytes  32.9 Mbits/sec  375             sender
[  5]   0.00-10.00  sec  37.7 MBytes  31.6 Mbits/sec                  receiver

तो मूल रूप से, SBC पर अपलोड करना लगभग 24MBits / sec तक पहुँच जाता है, और इससे डाउनलोड ( -R) 32MBits / sec तक पहुँच जाता है।

एसएसएच के साथ बेंचमार्किंग

यह देखते हुए, आइए देखें कि एसएसएच किराया कैसे है। मैंने पहली बार उन समस्याओं का अनुभव किया है जिनका उपयोग करते हुए इस पद का नेतृत्व किया rsyncऔर borgbackup- दोनों ने SSH का उपयोग परिवहन परत के रूप में किया ... तो चलिए देखते हैं कि SSH एक ही लिंक पर कैसा प्रदर्शन करता है:

# cat /dev/urandom | \
    pv -ptebar | \
    ssh  root@192.168.1.150 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]

खैर, यह एक घृणित गति है! अपेक्षित लिंक की गति की तुलना में बहुत धीमा ... (यदि आप इसके बारे में नहीं जानते हैं pv -ptevar: यह डेटा की वर्तमान और औसत दर को प्रदर्शित करता है। इस मामले में, हम देखते हैं कि /dev/urandomएसएसएच से अधिक डेटा को एसबीसी में भेजना और भेजना है। औसतन 400KB / s - यानी 3.2MBits / सेकंड तक पहुँचने की उम्मीद 24MBits / sec की तुलना में बहुत कम आंकड़ा है।)

हमारी लिंक अपनी क्षमता के 13% पर क्यों चल रही है?

क्या यह शायद हमारी /dev/urandomगलती है?

# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]

नहीं, निश्चित रूप से नहीं।

क्या यह शायद एसबीसी ही है? शायद यह प्रक्रिया के लिए बहुत धीमा है? आइए उसी SSH कमांड को चलाने का प्रयास करें (यानी SBC को डेटा भेजते हैं) लेकिन इस बार एक अन्य मशीन (मशीन 2) से जो ईथरनेट पर कनेक्ट है:

# cat /dev/urandom | \
    pv -ptebar | \
    ssh  root@192.168.1.150 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s] 

नहींं, यह ठीक काम करता है - एसबीसी पर SSH डेमन (आसानी से) 11MBytes / sec (यानी 100MBits / sec) को संभाल सकता है जो यह ईथरनेट लिंक प्रदान करता है।

और क्या ऐसा करते समय SBC का CPU लोड होता है?

सीपीयू आसानी से इसे संभाल रहा है

नहीं।

इसलिए...

  • नेटवर्क-वार (प्रति के अनुसार iperf3) हमें 10x गति करने में सक्षम होना चाहिए
  • हमारे सीपीयू आसानी से लोड को समायोजित कर सकते हैं
  • ... और हम किसी अन्य प्रकार के I / O (जैसे ड्राइव) को शामिल नहीं करते हैं।

क्या बिल्ली हो रही है?

बचाव के लिए Netcat और ProxyCommand

चलो सादे पुराने netcatकनेक्शन की कोशिश करते हैं - क्या वे उतनी ही तेजी से चलते हैं जितनी हम उम्मीद करेंगे?

SBC में:

# nc -l -p 9988 | pv -ptebar > /dev/null

लैपटॉप में:

# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s] 

यह काम करता हैं! और उम्मीद पर चलता है - बहुत बेहतर, 10x बेहतर - गति।

तो क्या होता है अगर मैं SSH का उपयोग करते हुए SSH को nc का उपयोग करने के लिए चलाता हूं?

# cat /dev/urandom | \
    pv -ptebar | \
    ssh -o "Proxycommand nc %h %p" root@192.168.1.150 'cat >/dev/null'
101MiB 0:00:30 [3.38MiB/s] [3.33MiB/s]

काम करता है! 10x की गति।

अब मैं थोड़ा उलझन में हूँ - जब एक "नग्न" का उपयोग कर ncएक के रूप में Proxycommand, आप मूल रूप से ठीक उसी बात यह है कि SSH करता है नहीं कर रहे हैं? यानी एक सॉकेट बनाना, SBC के पोर्ट 22 से कनेक्ट करना, और फिर उस पर SSH प्रोटोकॉल को शेव करना?

परिणामी गति में इतना बड़ा अंतर क्यों है?

PS यह एक अकादमिक अभ्यास नहीं था - borgइस वजह से मेरा बैकअप 10 गुना तेज है। मैं अभी पता नहीं क्यों :-)

संपादित करें : यहां प्रक्रिया का एक "वीडियो" जोड़ा गया । Ifconfig के आउटपुट से भेजे गए पैकेटों की गिनती करते हुए, यह स्पष्ट है कि दोनों परीक्षणों में हम 40MB डेटा भेज रहे हैं, उन्हें लगभग 30K पैकेटों में प्रेषित कर रहे हैं - उपयोग नहीं करते समय बस धीमा ProxyCommand


बफरिंग? मुझे लगता है कि ncलाइन बफरिंग का उपयोग करता है, जबकि sshकोई बफरिंग नहीं है। तो (या यदि ऐसा है) ssh यातायात में अधिक पैकेट शामिल हैं।
राल्फ रौनकवादी

मैं कोई विशेषज्ञ नहीं हूं, लेकिन मुझे लगता है कि नारंगी 0 में केवल एक usb बस है जिसे cpu द्वारा नियंत्रित किया जाता है, नेटवर्क उस usb बस से गुजरता है, cpu को सॉफ्टवेयर के माध्यम से यादृच्छिक संख्या बनानी होती है (उस तरह की वास्तुकला पर कोई चिप नहीं है जो उस माध्यम से करता है हार्डवेयर) और एक ही समय में ssh cy चल रहा है और शायद ssh संपीड़न भी। मैंने यह सब नहीं देखा, इसलिए यह संभव है कि मैं कुछ गलत कह रहा हूँ।
डी 'आर्सी नाडर

2
@ D'ArcyNader: नहीं, मुझे डर है कि आप इसे गलत समझ गए हैं। लैपटॉप (x86) में Tbe / dev / urandom होता है - और मैंने मशीन 2 से SBC से एक ही परीक्षण किया, शीर्ष गति (100MBits / sec) पर पहुंच गया, और इस प्रकार यह साबित कर दिया कि SBC के पास यातायात से निपटने के लिए कोई समस्या नहीं है। समस्या केवल तब प्रकट होती है जब SSH का उपयोग लैपटॉप से ​​किया जाता है - और जब मैं netcat का उपयोग करने के लिए SSH आह्वान (फिर से, लैपटॉप की तरफ) में परिवर्तन करता हूं - तो अभी भी देव / उरुग्म और अभी भी सभी डेटा को पाइप करते हुए - समस्या गायब हो जाती है। और BTW, सिंगल USB बस रास्पबेरी PIs की समस्या है - ऑरेंज PIs की नहीं।
ttsiodras

मुझे खेद है अगर मैंने आपकी मदद नहीं की। और स्पष्टीकरण के लिए धन्यवाद।
डी 'आर्सी नाडर

@ RalphRönnquist: मूल उपयोग मामला जिसने मुझे इस खरगोश छेद का नेतृत्व किया, वह rsync और बोर्गबैकअप पर चीजों का समर्थन कर रहा था। कई उपकरण SSH को एक परिवहन तंत्र के रूप में उपयोग करते हैं - और मेरे मामले में, इस वजह से पीड़ित हैं। अगर मैं जो अनुभव कर रहा हूं, वह वास्तव में "मानक" SSH व्यवहार है, तो मैं उम्मीद करूंगा कि SSC को एक netcat प्रॉक्सी के माध्यम से सभी बैकअप टूल के लिए पुल अनुरोध सबमिट करने से ProxyCommand तुरंत पूरे ग्रह पर बैकअप को गति देगा! मुझे विश्वास नहीं हो रहा है कि मैंने ऐसी "विशाल" खोज की है :-) यहां कुछ और हो रहा होगा।
ttsiodras

जवाबों:


14

उन लोगों को बहुत धन्यवाद, जिन्होंने टिप्पणियों में विचार प्रस्तुत किए। मैं उन सभी के माध्यम से चला गया:

Tcpdump के साथ पैकेट की रिकॉर्डिंग और वायरशार्क में सामग्री की तुलना

# tcpdump -i wlan0 -w good.ssh & \
     cat signature | ssh -o "ProxyCommand nc %h %p" \
        root@192.168.1.150 'cat | md5sum' ; \
     killall tcpdump
# tcpdump -i wlan0 -w bad.ssh & \
     cat signature | ssh root@192.168.1.150 'cat | md5sum' ; \
     killall tcpdump

दर्ज पैकेटों में कोई महत्व का अंतर नहीं था।

यातायात को आकार देने के लिए जाँच कर रहा है

इस बारे में कोई पता नहीं था - लेकिन "टीसी" मैनपेज को देखने के बाद, मैं इसे सत्यापित करने में सक्षम था

  • tc filter show कुछ नहीं देता
  • tc class show कुछ नहीं देता
  • tc qdisc show

... ये देता है:

qdisc noqueue 0: dev lo root refcnt 2
qdisc noqueue 0: dev docker0 root refcnt 2
qdisc fq_codel 0: dev wlan0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn 

... जो "ssh" और "nc" के बीच अंतर करने के लिए प्रतीत नहीं होता है - वास्तव में, मुझे यह भी पक्का नहीं है कि ट्रैफ़िक को आकार देने की प्रक्रिया स्तर पर काम कर सकती है (मुझे इसके पते / पोर्ट / विभेदित पर काम करने की उम्मीद है) आईपी ​​हेडर में सेवा क्षेत्र)।

डेबियन चेरोट, आर्क लिनक्स एसएसएच क्लाइंट में संभावित "चतुराई" से बचने के लिए

नहीं, एक ही परिणाम।

अंत में - नागले

प्रेषक में एक स्ट्रेस करना ...

pv data | strace -T -ttt -f ssh 192.168.1.150 'cat | md5sum' 2>bad.log

... और उस सॉकेट पर जो वास्तव में डेटा को प्रसारित करता है, उसे देखकर, मैंने वास्तविक संचारण से पहले इस "सेटअप" को देखा:

1522665534.007805 getsockopt(3, SOL_TCP, TCP_NODELAY, [0], [4]) = 0 <0.000025>
1522665534.007899 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000021>

यह नागल के एल्गोरिथ्म को अक्षम करने के लिए एसएसएच सॉकेट स्थापित करता है। आप Google और इसके बारे में सभी पढ़ सकते हैं - लेकिन इसका क्या मतलब है, यह है कि एसएसएच बैंडविड्थ पर जवाबदेही को प्राथमिकता दे रहा है - यह कर्नेल को इस सॉकेट पर लिखी गई किसी भी चीज को तुरंत प्रसारित करने का निर्देश देता है और रिमोट से प्राप्त होने के इंतजार में "देरी" नहीं करता है।

सादे शब्दों में, इसका मतलब यह है कि अपने डिफ़ॉल्ट कॉन्फ़िगरेशन में, SSH डेटा को पार करने का एक अच्छा तरीका नहीं है - न कि जब लिंक का उपयोग धीमा है (जो कई वाईफाई लिंक के लिए मामला है)। अगर हम हवा में पैकेट भेज रहे हैं जो "ज्यादातर हेडर" हैं, तो बैंडविड्थ बर्बाद हो गया है!

यह साबित करने के लिए कि यह वास्तव में अपराधी था, मैंने LD_PRELOAD का उपयोग इस विशिष्ट syscall को "ड्रॉप" करने के लिए किया:

$ cat force_nagle.c

#include <stdio.h>
#include <dlfcn.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>

int (*osetsockopt) (int socket, int level, int option_name,
           const void *option_value, socklen_t option_len) = NULL;

int setsockopt(int socket, int level, int option_name,
           const void *option_value, socklen_t option_len)
{
    int ret;
    if (!osetsockopt) {
        osetsockopt = dlsym(RTLD_NEXT, "setsockopt");
    }

    if (option_name == TCP_NODELAY) {
        puts("No, Mr Nagle stays.");
        return 0;
    }
    ret = osetsockopt(socket, level, option_name, option_value, option_len);
    return ret;
}

$ gcc -fPIC -D_GNU_SOURCE -shared -o force_nagle.so force_nagle.c -ldl

$ pv /dev/shm/data | LD_PRELOAD=./force_nagle.so ssh root@192.168.1.150 'cat >/dev/null'
No, Mr Nagle stays.
No, Mr Nagle stays.
 100MiB 0:00:29 [3.38MiB/s] [3.38MiB/s] [================================>] 100%   

वहाँ - सही गति (ठीक है, बस के रूप में तेजी से iperf3)।

कहानी का मनोबल

कभी हार मत मानो :-)

और अगर आप की तरह उपकरणों का उपयोग करते हैं rsyncया borgbackupया का उपयोग कर - SSH पर कि परिवहन अपने डेटा, और आपके लिंक एक धीमी गति से एक है, Nagle अक्षम करने से SSH रोक (जैसा कि ऊपर दिखाया गया है) की कोशिश ProxyCommandस्विच SSH के माध्यम से कनेक्ट करने के लिए nc। इसे आपके $ HOME / .ssh / config में स्वचालित किया जा सकता है:

$ cat .ssh/config
...
Host orangepi
    Hostname 192.168.1.150
    User root
    Port 22
    # Compression no
    # Cipher None
    ProxyCommand nc %h %p
...

... ताकि ssh / rsync / borgbackup में एक लक्ष्य होस्ट के रूप में "ऑरेंजपीआई" के सभी भविष्य के उपयोगों ncको कनेक्ट करने के लिए उपयोग किया जाएगा (और इसलिए नागल को अकेला छोड़ दें)।


धन्यवाद, आपने मेरी जान बचाई! क्या आपने यह समझने के लिए ssh लोगों से संपर्क करने की कोशिश की कि इसे नियंत्रित करने के लिए कोई सेटिंग क्यों नहीं है?
स्थिर_पार्टी

1
मुझे खुशी है कि मेरे निष्कर्षों ने आपकी भी मदद की! SSH लोगों से संपर्क करने के लिए, मैंने कोशिश की, हाँ - लेकिन कुछ भी नहीं हुआ, अंत में: Bugzilla.mindrot.org/show_bug.cgi?id=2848
ttsiodras

खुद को बग से जोड़ा। कौन जानता है, कुछ अंततः हो सकता है! महान जांच, किसी भी मामले में।
static_rtti
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.