ওপেনএসএসএইচ রিমোট ফরওয়ার্ডের জন্য গতিশীল বরাদ্দকৃত বন্দর নির্ধারণ করুন


13

প্রশ্ন (টিএল; ডিআর)

রিমোট ফরওয়ার্ডিং (ওরফে -Rবিকল্প) জন্য গতিশীলভাবে পোর্টগুলি বরাদ্দ করার সময়, দূরবর্তী মেশিনে কোনও স্ক্রিপ্ট (উদাহরণস্বরূপ উত্স থেকে .bashrc) কীভাবে নির্ধারণ করতে পারে যে কোন পোর্টগুলি ওপেনএসএইচ দ্বারা নির্বাচিত হয়েছিল?


পটভূমি

আমি আমাদের কেন্দ্রীয় সার্ভারে সংযোগ রাখতে ওপেনএসএইচ (উভয় প্রান্তে) ব্যবহার করি যা আমি একাধিক অন্যান্য ব্যবহারকারীর সাথে ভাগ করি। আমার দূরবর্তী সেশনের জন্য (এখনের জন্য) আমি এক্স, কাপ এবং পালসওদিও ফরোয়ার্ড করতে চাই।

-Xবিকল্পটি ব্যবহার করে সর্বাধিক তুচ্ছটি ফরওয়ার্ডিং এক্স । বরাদ্দ হওয়া এক্স ঠিকানাটি পরিবেশগত পরিবর্তনশীলতে সঞ্চয় করা হয় DISPLAYএবং সেখান থেকে আমি সংশ্লিষ্ট টিসিপি বন্দরটি নির্ধারণ করতে পারি, বেশিরভাগ ক্ষেত্রেই হোক। তবে আমার খুব কমই দরকার, কারণ এক্সলিব সম্মান দেয় DISPLAY

কাপ এবং পালসওদিওয়ের জন্য আমার অনুরূপ প্রক্রিয়া দরকার। দুটি পরিষেবার জন্য বুনিয়াদি অস্তিত্ব, পরিবেশগত ভেরিয়েবল আকারে CUPS_SERVERএবং PULSE_SERVERযথাক্রমে। এখানে ব্যবহারের উদাহরণ রয়েছে:

ssh -X -R12345:localhost:631 -R54321:localhost:4713 datserver

export CUPS_SERVER=localhost:12345
lowriter #and I can print using my local printer
lpr -P default -o Duplex=DuplexNoTumble minutes.pdf #printing through the tunnel
lpr -H localhost:631 -P default -o Duplex=DuplexNoTumble minutes.pdf #printing remotely

mpg123 mp3s/van_halen/jump.mp3 #annoy co-workers
PULSE_SERVER=localhost:54321 mpg123 mp3s/van_halen/jump.mp3 #listen to music through the tunnel

সমস্যাটি সেট করা হচ্ছে CUPS_SERVERএবং PULSE_SERVERসঠিকভাবে।

আমরা পোর্ট ফরওয়ার্ডিংগুলি প্রচুর ব্যবহার করি এবং তাই আমার গতিশীল পোর্ট বরাদ্দ প্রয়োজন। স্ট্যাটিক পোর্ট বরাদ্দ কোনও বিকল্প নয়।

রিমোট সার্ভারে গতিশীল পোর্ট বরাদ্দের জন্য ওপেনএসএইচের একটি ব্যবস্থা রয়েছে, 0রিমোট ফরওয়ার্ডিং ( -Rবিকল্প) জন্য বাইন্ড-পোর্ট হিসাবে নির্দিষ্ট করে । নিম্নলিখিত কমান্ডটি ব্যবহার করে, ওপেনএসএইচটি কাপ এবং পালস ফরোয়ার্ডিংয়ের জন্য গতিশীলভাবে পোর্ট বরাদ্দ করবে।

ssh -X -R0:localhost:631 -R0:localhost:4713 datserver

যখন আমি এই কমান্ডটি ব্যবহার sshকরব, নিম্নলিখিতগুলি মুদ্রণ করব STDERR:

Allocated port 55710 for remote forward to 127.0.0.1:4713
Allocated port 41273 for remote forward to 127.0.0.1:631

আমি চাই তথ্য আছে! শেষ পর্যন্ত আমি উত্পন্ন করতে চাই:

export CUPS_SERVER=localhost:41273
export PULSE_SERVER=localhost:55710

তবে "বরাদ্দকৃত বন্দর ..." বার্তা আমার স্থানীয় মেশিনে তৈরি হয়েছে এবং প্রেরণ করা হয়েছে STDERR, যা আমি দূরবর্তী মেশিনে অ্যাক্সেস করতে পারি না। অদ্ভুতভাবে যথেষ্ট যে ওপেনএসএইচ-এর কাছে পোর্ট ফরওয়ার্ডিং সম্পর্কিত তথ্য পুনরুদ্ধার করার উপায় আছে বলে মনে হয় না।

পর্যাপ্তভাবে সেট করতে CUPS_SERVERএবং PULSE_SERVERদূরবর্তী হোস্টে শেল স্ক্রিপ্টে রাখার জন্য আমি কীভাবে এই তথ্যটি আনব?


মৃত শেষ

sshdলগগুলি থেকে তথ্যটি পড়া না পাওয়া পর্যন্ত আমি খুঁজে পেলাম কেবলমাত্র সহজ জিনিস ver এটি বাস্তবসম্মত নয় কারণ তথ্যটি অ-রুট ব্যবহারকারীদের অ্যাক্সেসযোগ্য করার চেয়ে বোধগম্যতার চেয়ে অনেক বেশি তথ্য প্রকাশ করে।

আমি অতিরিক্ত এস্কেপ সিকোয়েন্সকে সমর্থন করার জন্য ওপেনএসএইচ প্যাচিংয়ের কথা ভাবছিলাম যা অভ্যন্তরীণ কাঠামোর একটি দুর্দান্ত উপস্থাপনা মুদ্রণ করে permitted_opens, তবে এটি আমি চাইলেও, আমি এখনও সার্ভার দিক থেকে ক্লায়েন্টের পালানোর ক্রমগুলি অ্যাক্সেস করতে স্ক্রিপ্ট করতে পারি না।


আরও ভাল উপায় থাকতে হবে

নিম্নলিখিত পদ্ধতিটি খুব অস্থির বলে মনে হচ্ছে এবং ব্যবহারকারী হিসাবে এই জাতীয় একটি এসএসএইচ সেশনের মধ্যে সীমাবদ্ধ। তবে, আমার কমপক্ষে দুটি একই ধরণের সেশন এবং অন্যান্য ব্যবহারকারীদের আরও বেশি প্রয়োজন need তবে আমি চেষ্টা করেছিলাম ...

তারকারা যখন সঠিকভাবে সারিবদ্ধ হয়, একটি মুরগী ​​বা দুটি বলি উত্সর্গ করার পরে, আমি এই বিষয়টি sshdআমার ব্যবহারকারী হিসাবে শুরু করা হয়নি তা অপব্যবহার করতে পারি, তবে এটি সফল করার জন্য সফল লগইনের পরে সুযোগগুলি বাদ দেয়:

  • আমার ব্যবহারকারীর অন্তর্ভুক্ত সমস্ত শ্রোতা সকেটের জন্য পোর্ট নম্বরের একটি তালিকা পান

    netstat -tlpen | grep ${UID} | sed -e 's/^.*:\([0-9]\+\) .*$/\1/'

  • আমার ব্যবহারকারী শুরু হওয়া প্রক্রিয়াগুলির সাথে সম্পর্কিত সমস্ত শ্রবণকারী সকেটের জন্য পোর্ট নম্বরের একটি তালিকা পান

    lsof -u ${UID} 2>/dev/null | grep LISTEN | sed -e 's/.*:\([0-9]\+\) (LISTEN).*$/\1/'

  • সমস্ত পোর্ট যে প্রথম সেটে আছে, কিন্তু দ্বিতীয় সেটে একটি উচ্চ likelyhood আমার ফরওয়ার্ডিং পোর্ট, এবং প্রকৃতপক্ষে সেট উৎপাদনের বিয়োগ হতে না 41273, 55710এবং 6010; যথাক্রমে কাপ, ডাল এবং এক্স।

  • 6010এক্স বন্দর ব্যবহার করে চিহ্নিত করা হয় DISPLAY

  • 41273কাপ কাপ, কারণ lpstat -h localhost:41273 -aফিরে 0
  • 55710নাড়ি বন্দর, কারণ pactl -s localhost:55710 statফিরে আসে 0। (এটি এমনকি আমার ক্লায়েন্টের হোস্টনামটিও প্রিন্ট করে!)

(আমি সেট বিয়োগের কাজটি করতে sort -uএবং উপরের কমান্ড লাইনগুলি থেকে আউটপুট সঞ্চয় commকরতে এবং বিয়োগফলটি করতে ব্যবহার করুন ))

পালসোদিও আমাকে ক্লায়েন্ট সনাক্ত করতে দেয় এবং সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে, এটি এসএসএইচ সেশনগুলির পৃথককরণের জন্য নোঙ্গর হিসাবে কাজ করতে পারে। যাইহোক, আমি গিঁট একটি উপায় খুঁজে পেলাম না 41273, 55710এবং 6010একই sshdপ্রক্রিয়া। netstatঅ-রুট ব্যবহারকারীদের কাছে সেই তথ্য প্রকাশ করবে না। আমি তো পেতে -মধ্যে PID/Program nameকলাম যেখানে আমি পড়তে চাই 2339/54(এই বিশেষ ইনস্ট্যান্সের মধ্যে)। খুব কাছে ...


তবে, এটি বলা আরও সঠিক যে netstatএটি আপনার নিজের নয় এমন প্রসেসের জন্য পিআইডি প্রদর্শন করবে না যা কার্নেল-স্পেস। উদাহরণস্বরূপ
ব্র্যাচলে 13'77

সবচেয়ে শক্তিশালী উপায় হ'ল প্যাচ প্যাচ করা ... একটি দ্রুত এবং নোংরা প্যাচ কেবলমাত্র কয়েকটি লাইন হবে যেখানে সার্ভার ওএস থেকে স্থানীয় পোর্ট পায়, একটি ফাইলটিতে পোর্ট নম্বর লিখবে, ব্যবহারকারীর নাম, রিমোট হোস্ট এবং বন্দর। ধরে নেওয়া সার্ভার ক্লায়েন্ট পক্ষের বন্দরটি জানে, যা নির্দিষ্ট নয়, সম্ভবত সম্ভাবনাও নেই (অন্যথায় বৈশিষ্ট্যটি ইতিমধ্যে উপস্থিত থাকবে)।
হাইড

@ হাইড: হুবহু দূরবর্তী সার্ভারটি ফরওয়ার্ড করা পোর্টগুলি সম্পর্কে জানে না। এটি কেবল কয়েকটি শ্রোতা সকেট তৈরি করে এবং ডেটা এসএসএস সংযোগের মাধ্যমে ফরোয়ার্ড করা হয়। এটি স্থানীয় গন্তব্য বন্দরগুলি সম্পর্কে জানে না।
বনাঙ্গুইন

উত্তর:


1

দুটি নিন (কোনও সংস্করণের ইতিহাস দেখুন যা সার্ভার দিক থেকে স্ক্রিপ হয় এবং এটি কিছুটা সহজ), এটি করা উচিত। এর সংক্ষেপটি হ'ল:

  1. ক্লায়েন্ট থেকে সার্ভারে একটি পরিবেশের পরিবর্তনশীল পাস করুন, সার্ভারকে জানান যে পোর্ট তথ্য কখনই পাওয়া যায় এবং কীভাবে এটি ব্যবহার করতে পারে তা কীভাবে সনাক্ত করতে পারে।
  2. একবার পোর্ট তথ্য পাওয়া গেলে, এটি ক্লায়েন্ট থেকে সার্ভারে অনুলিপি করুন, সার্ভারকে এটির অনুমতি দেয় (উপরের অংশের সাহায্যে) এবং এটি ব্যবহার করুন

প্রথমে, রিমোট সাইডে সেটআপ করার জন্য আপনাকে এসএসডিডি কনফিগারেশনে এনভিভি ভেরিয়েবল প্রেরণ সক্ষম করতে হবে :

sudo yourfavouriteeditor /etc/ssh/sshd_config

এর সাথে লাইন সন্ধান AcceptEnvকরুন এবং এতে যুক্ত করুন MY_PORT_FILE(বা Hostএখনও পর্যন্ত না থাকলে ডান বিভাগের অধীনে লাইন যুক্ত করুন )। আমার জন্য লাইনটি এটি হয়ে গেল:

AcceptEnv LANG LC_* MY_PORT_FILE

এটি কার্যকর হওয়ার জন্য sshd পুনরায় চালু করতে ভুলবেন না।

অতিরিক্তভাবে, নীচের স্ক্রিপ্টগুলির কাজ করার জন্য, mkdir ~/portfilesদূরবর্তী দিক থেকে করুন!


তারপরে স্থানীয় দিকে, একটি স্ক্রিপ্ট স্নিপেট যা হবে

  1. স্ট্যাডার পুনঃনির্দেশের জন্য টেম্প ফাইলের নাম তৈরি করুন
  2. বিষয়বস্তু থাকার জন্য ফাইলটির জন্য অপেক্ষা করতে একটি পটভূমি কাজ ছেড়ে দিন
  3. সার্ভারে ফাইলের নাম env ভেরিয়েবল হিসাবে পাস করুন, যখন ssh stderr কে ফাইলে পুনর্নির্দেশ করবেন
  4. ব্যাকগ্রাউন্ড কাজ পৃথক স্ক্রিপ ব্যবহার করে স্ট্যাডার টেম্প ফাইলটি সার্ভারের পাশে অনুলিপি করে চলেছে
  5. ব্যাকগ্রাউন্ড জব স্টার্ডার ফাইল প্রস্তুত তা চিহ্নিত করতে সার্ভারে একটি পতাকা ফাইলও অনুলিপি করে

স্ক্রিপ্ট স্নিপেট:

REMOTE=$USER@datserver

PORTFILE=`mktemp /tmp/sshdataserverports-$(hostname)-XXXXX`
test -e $PORTFILE && rm -v $PORTFILE

# EMPTYFLAG servers both as empty flag file for remote side,
# and safeguard for background job termination on this side
EMPTYFLAG=$PORTFILE-empty
cp /dev/null $EMPTYFLAG

# this variable has the file name sent over ssh connection
export MY_PORT_FILE=$(basename $PORTFILE)

# background job loop to wait for the temp file to have data
( while [ -f $EMPTYFLAG -a \! -s $PORTFILE ] ; do
     sleep 1 # check once per sec
  done
  sleep 1 # make sure temp file gets the port data

  # first copy temp file, ...
  scp  $PORTFILE $REMOTE:portfiles/$MY_PORT_FILE

  # ...then copy flag file telling temp file contents are up to date
  scp  $EMPTYFLAG $REMOTE:portfiles/$MY_PORT_FILE.flag
) &

# actual ssh terminal connection    
ssh -X -o "SendEnv MY_PORT_FILE" -R0:localhost:631 -R0:localhost:4713 $REMOTE 2> $PORTFILE

# remove files after connection is over
rm -v $PORTFILE $EMPTYFLAG

তখন দূরবর্তী পাশের একটি স্নিপেট, জন্য উপযুক্ত .bashrc :

# only do this if subdir has been created and env variable set
if [ -d ~/portfiles -a "$MY_PORT_FILE" ] ; then

       PORTFILE=~/portfiles/$(basename "$MY_PORT_FILE")
       FLAGFILE=$PORTFILE.flag
       # wait for FLAGFILE to get copied,
       # after which PORTFILE should be complete
       while [ \! -f "$FLAGFILE" ] ; do 
           echo "Waiting for $FLAGFILE..."
           sleep 1
       done

       # use quite exact regexps and head to make this robust
       export CUPS_SERVER=localhost:$(grep '^Allocated port [0-9]\+ .* localhost:631[[:space:]]*$' "$PORTFILE" | head -1 | cut -d" " -f3)
       export PULSE_SERVER=localhost:$(grep '^Allocated port [0-9]\+ .* localhost:4713[[:space:]]*$' "$PORTFILE" | head -1 | cut -d" " -f3)
       echo "Set CUPS_SERVER and PULSE_SERVER"

       # copied files served their purpose, and can be removed right away
       rm -v -- "$PORTFILE" "$FLAGFILE"
fi

দ্রষ্টব্য : উপরের কোডটি অবশ্যই খুব পুঙ্খানুপুঙ্খভাবে পরীক্ষিত নয় এবং এতে সমস্ত ধরণের বাগ, অনুলিপি-পেস্ট ত্রুটি থাকতে পারে ইত্যাদি যে কেউ এটিকে আরও ভালভাবে ব্যবহার করে তাও বুঝতে পারে, নিজের ঝুঁকিতে ব্যবহার করুন! আমি এটি কেবল লোকালহোস্ট সংযোগ ব্যবহার করে পরীক্ষা করেছি এবং এটি আমার পরীক্ষার vর্ষায় আমার জন্য কাজ করেছে। YMMV।


কোনটি অবশ্যই আমি scpদূরবর্তী দিক থেকে স্থানীয় দিকে যেতে পারি, যা আমি পারি না। আমার অনুরূপ পন্থা ছিল, তবে sshসংযোগ স্থাপনের পরে আমি এটি ব্যাকগ্রাউন্ডে গুটিয়ে দেব , তারপরে সেই ফাইলটি স্থানীয় থেকে দূরবর্তী হয়ে প্রেরণ করুন scpএবং তারপরে sshক্লায়েন্টটিকে অগ্রভাগে টানুন এবং রিমোট দিকে স্ক্রিপ্ট চালান run স্থানীয় এবং দূরবর্তী প্রক্রিয়াগুলি কীভাবে স্ক্রিপ্টের পটভূমি তৈরি করতে এবং পূর্বাভাস দেওয়া যায় তা আমি খুঁজে পাইনি। স্থানীয় sshক্লায়েন্টকে এমন কিছু দূরবর্তী স্ক্রিপ্টগুলির সাথে মোড়ানো এবং সংহত করা ভাল পদ্ধতির মতো বলে মনে হয় না।
বনাঙ্গুইন

আহ। আমার মনে হয় আপনি পটভূমি ক্লায়েন্ট সাইড উচিত scp কমান্ড শুধুমাত্র: (while [ ... ] ; do sleep 1 ; done ; scp ... )&। তারপরে .bashrcফাইলটি উপস্থিত হওয়ার জন্য সার্ভারের অগ্রভাগের জন্য অপেক্ষা করুন (ক্লায়েন্টটি ডান এনভ ভেরিয়েবল প্রেরণ করে)। আমি কিছু পরীক্ষার পরে উত্তরটি আপডেট করব (সম্ভবত আগামীকাল পর্যন্ত কোনও সময় নেই)।
হাইড

@ বনানগুইন নতুন সংস্করণ সম্পন্ন হয়েছে। আমার জন্য কাজ করে মনে হচ্ছে, তাই আপনার ব্যবহারের ক্ষেত্রে খাপ খাইয়ে নেওয়া উচিত। "চমৎকার পদ্ধতির" সম্পর্কে, হ্যাঁ, তবে আমি মনে করি না এখানে সত্যিই একটি দুর্দান্ত পদ্ধতির সম্ভাবনা রয়েছে। তথ্যটি কোনওভাবেই পাস করা দরকার, এবং এটি সর্বদা হ্যাক হতে চলেছে, যদি না আপনি একক সংযোগের উপর পরিষ্কারভাবে এটি করার জন্য ssh ক্লায়েন্ট এবং সার্ভার উভয়কেই প্যাচ করেন।
হাইড

এবং আমি ওপেনশ প্যাচিং সম্পর্কে আরও বেশি করে ভাবছি। বড় ব্যাপার বলে মনে হয় না। তথ্য ইতিমধ্যে উপলব্ধ। আমার এটি সার্ভারে প্রেরণ করা দরকার। সার্ভার যখনই এই জাতীয় তথ্য পেয়ে থাকে তখন তা এতে লিখে দেয়~/.ssh-${PID}-forwards
বনাঙ্গুইন

1

স্থানীয় পক্ষের জন্য একটি স্নিপেট, .বাশার্কের জন্য উপযুক্ত:

#!/bin/bash

user=$1
host=$2

sshr() {
# 1. connect, get dynamic port, disconnect  
port=`echo "exit" | ssh -R '*:0:127.0.0.1:52698' -t $1 2>&1 | grep 'Allocated port' | awk '/port/ {print $3;}'`
# 2. reconnect with this port and set remote variable
cmds="ssh -R $port:127.0.0.1:52698 -t $1 bash -c \"export RMATE_PORT=$port; bash\""
($cmds)
}

sshr $user@$host

0

স্থানীয় ক্লায়েন্টে পাইপ তৈরি করে আমি এটি অর্জন করেছি, তারপরে স্ট্যাডারকে পাইপে পুনর্নির্দেশ করে যা এসএসএসের ইনপুটটিতেও পুনঃনির্দেশিত হয়। এটি একটি মুক্ত পরিচিত বন্দর অনুমান করতে একাধিক ssh সংযোগের প্রয়োজন নেই যা ব্যর্থ হতে পারে। এভাবে লগন ব্যানার এবং "বরাদ্দকৃত পোর্ট ### ..." পাঠ্য দূরবর্তী হোস্টে পুনঃনির্দেশিত হয়।

আমার কাছে হোস্টটিতে একটি সহজ স্ক্রিপ্ট রয়েছে getsshport.shযা দূরবর্তী হোস্টে চালিত হয় যা পুনর্নির্দেশিত ইনপুট পড়ে এবং পোর্টটি পার্স করে দেয়। যতক্ষণ না এই স্ক্রিপ্টটি শেষ হয় না, ততক্ষণ ssh রিমোট ফরোয়ার্ড খোলা থাকে।

স্থানীয় দিক

mkfifo pipe
ssh -R "*:0:localhost:22" user@remotehost "~/getsshport.sh" 3>&1 1>&2 2>&3 < pipe | cat > pipe

3>&1 1>&2 2>&3 স্ট্যাডার এবং স্টডআউটকে অদলবদল করার জন্য একটি সামান্য কৌশল, যাতে স্টার্ডার বিড়ালের কাছে পাইপ হয় এবং এসএসএস থেকে প্রাপ্ত সমস্ত সাধারণ আউটপুট স্টডারারে প্রদর্শিত হয়।

রিমোট সাইড gets / getshport.sh

#!/bin/sh
echo "Connection from $SSH_CLIENT"
while read line
do
    echo "$line" # echos everything sent back to the client
    echo "$line" | sed -n "s/Allocated port \([0-9]*\) for remote forward to \(.*\)\:\([0-9]*\).*/client port \3 is on local port \1/p" >> /tmp/allocatedports
done

আমি grepপ্রথমে স্থানীয় পক্ষের "বরাদ্দকৃত বন্দর" বার্তাটি ssh এর মাধ্যমে প্রেরণের আগে চেষ্টা করেছিলাম , তবে মনে হয় যে এসএসডি পাইপটি স্টিডিনে খোলার অপেক্ষায় অবরুদ্ধ হবে। কিছু কিছু না পাওয়া পর্যন্ত গ্রেপ লেখার জন্য পাইপ খোলেন না, সুতরাং এটি মূলত অচল। catতবে এই একই আচরণ বলে মনে হয় না এবং এসএসএসকে সংযোগটি খোলার অনুমতি দেওয়ার সাথে সাথেই লেখার জন্য পাইপটি খোলে।

এটি দূরবর্তী দিকের একই সমস্যা, এবং কেন readস্টিডিনের থেকে কেবল গ্রেপের পরিবর্তে লাইনে লাইন লাইন করা - অন্যথায় tun / tmp / বরাদ্দগুলি 'এসএসএস টানেলটি বন্ধ না করা পর্যন্ত লিখিত হয় না যা পুরো উদ্দেশ্যকে পরাস্ত করে ts

Ssh এর stderr এর মতো ~/getsshport.shএকটি কমান্ডে পাইপ দেওয়া পছন্দ করা হয়, যেমন কোনও কমান্ড নির্দিষ্ট না করেই ব্যানার পাঠ্য বা পাইপটিতে যা আছে তা দূরবর্তী শেলের উপর কার্যকর হয়।


সুন্দর। আমি সংস্থান সংরক্ষণ করার renice +10 $$; exec catআগে যোগ done
স্পঞ্জম্যান

0

এটি একটি জটিল, অতিরিক্ত সার্ভার-সাইড হ্যান্ডলিংয়ের লাইন ধরে SSH_CONNECTIONবা DISPLAYদুর্দান্ত হবে তবে এটি যুক্ত করা সহজ নয়: সমস্যার অংশটি হ'ল কেবল sshক্লায়েন্ট স্থানীয় গন্তব্য জানেন, অনুরোধ প্যাকেটটি (সার্ভারের সাথে) রয়েছে কেবল দূরবর্তী ঠিকানা এবং বন্দর।

এখানে অন্যান্য উত্তরের এই ক্লায়েন্টের পক্ষটি ক্যাপচার এবং এটি সার্ভারে প্রেরণের জন্য বিভিন্ন অযৌক্তিক সমাধান রয়েছে। এখানে একটি বিকল্প পন্থা যা সততার পক্ষে খুব বেশি সুন্দর নয়, তবে কমপক্ষে এই কুরুচিপূর্ণ দলটি ক্লায়েন্টের পাশে রাখা হয়েছে ;-)

  • ক্লায়েন্ট পক্ষ, যুক্ত / সংশোধন করুন SendEnvযাতে আমরা কিছু পরিবেশের ভেরিয়েবল স্থানীয়ভাবে এসএসএসের মাধ্যমে প্রেরণ করতে পারি (সম্ভবত ডিফল্ট নয়)
  • সার্ভার সাইড, AcceptEnvএকই গ্রহণ করতে সংশোধন / সংশোধন করুন (সম্ভবত এটি ডিফল্টরূপে সক্ষম নয়)
  • sshএকটি গতিশীল লোড লাইব্রেরি সহ ক্লায়েন্ট স্টডার আউটপুট নিরীক্ষণ করুন এবং সংযোগ স্থাপনের সময় ssh ক্লায়েন্ট পরিবেশ আপডেট করুন
  • প্রোফাইল / লগইন স্ক্রিপ্টে পরিবেশের ভেরিয়েবল সার্ভারের দিকটি বাছাই করুন pick

এটি (আনন্দের সাথে, এখন যাইহোক) কার্যকর হয় কারণ পরিবেশের বিনিময় হওয়ার আগেই রিমোট ফরওয়ার্ড সেট আপ করা হয় এবং রেকর্ড করা হয় (এর সাথে নিশ্চিত করুন ssh -vv ...)। ডায়নামিকালি লোড করা লাইব্রেরিতে write()libc ফাংশন ( ssh_confirm_remote_forward()logit()do_log()write()) ক্যাপচার করতে হয় । কোনও ইএলএফ বাইনারি (পুনরায় সংশোধন না করে) ফাংশনগুলি পুনর্নির্দেশ করা বা মোড়ানো হ'ল ডায়নামিক লাইব্রেরিতে কোনও ক্রিয়াকলাপের জন্য এটি করার চেয়ে আরও জটিলতার আদেশ।

ক্লায়েন্টে .ssh/config(বা কমান্ড লাইন -o SendEnv ...)

Host somehost
  user whatever
  SendEnv SSH_RFWD_*

সার্ভারে sshd_config(রুট / প্রশাসনিক পরিবর্তন প্রয়োজন)

AcceptEnv LC_* SSH_RFWD_*

এই পদ্ধতির লিনাক্স ক্লায়েন্টদের জন্য কাজ করে এবং সার্ভারে বিশেষ কোনও কিছুই প্রয়োজন না, এটি অন্যান্য * নিক্সের জন্য কিছু ছোটখাটো টুইট সহ কাজ করা উচিত। কমপক্ষে ওপেনএসএসএইচ 5.8 পি 1 থেকে 7.5 পি 1 পর্যন্ত কাজ করে।

সাথে দাওয়াত দিয়ে gcc -Wall -shared -ldl -Wl,-soname,rfwd -o rfwd.so rfwd.c সংকলন:

LD_PRELOAD=./rfwd.so ssh -R0:127.0.0.1:4713 -R0:localhost:631 somehost

কোড:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>

// gcc -Wall -shared  -ldl -Wl,-soname,rfwd -o rfwd.so rfwd.c

#define DEBUG 0
#define dfprintf(fmt, ...) \
    do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
          __FILE__, __LINE__, __func__,##__VA_ARGS__); } while (0)

typedef ssize_t write_fp(int fd, const void *buf, size_t count);
static write_fp *real_write;

void myinit(void) __attribute__((constructor));
void myinit(void)
{
    void *dl;
    dfprintf("It's alive!\n");
    if ((dl=dlopen(NULL,RTLD_NOW))) {
        real_write=dlsym(RTLD_NEXT,"write");
        if (!real_write) dfprintf("error: %s\n",dlerror());
        dfprintf("found %p write()\n", (void *)real_write);
    } else {
        dfprintf(stderr,"dlopen() failed\n");
    }
}

ssize_t write(int fd, const void *buf, size_t count)
{
     static int nenv=0;

     // debug1: Remote connections from 192.168.0.1:0 forwarded to local address 127.0.0.1:1000
     //  Allocated port 44284 for remote forward to 127.0.0.1:1000
     // debug1: All remote forwarding requests processed
     if ( (fd==2) && (!strncmp(buf,"Allocated port ",15)) ) {
         char envbuf1[256],envbuf2[256];
         unsigned int rport;
         char lspec[256];
         int rc;

         rc=sscanf(buf,"Allocated port %u for remote forward to %256s",
          &rport,lspec);

         if ( (rc==2) && (nenv<32) ) {
             snprintf(envbuf1,sizeof(envbuf1),"SSH_RFWD_%i",nenv++);
             snprintf(envbuf2,sizeof(envbuf2),"%u %s",rport,lspec);
             setenv(envbuf1,envbuf2,1);
             dfprintf("setenv(%s,%s,1)\n",envbuf1,envbuf2);
         }
     }
     return real_write(fd,buf,count);
}

(এই পদ্ধতির সাথে প্রতীক সংস্করণ সম্পর্কিত কিছু গলিবুক ভালুকের ফাঁদ রয়েছে, তবে write()এই সমস্যাটি নেই))

যদি আপনি সাহসী বোধ করেন তবে আপনি setenv()সম্পর্কিত কোডটি নিতে এবং ssh.c ssh_confirm_remote_forward()কলব্যাক ফাংশনে প্যাচ করতে পারেন ।

এটি নামক পরিবেশ পরিবর্তনশীল সেট করে SSH_RFWD_nnn, আপনার প্রোফাইলে এগুলি পরীক্ষা করে, যেমনbash

for fwd in ${!SSH_RFWD_*}; do
    IFS=" :" read lport rip rport <<< ${!fwd}
    [[ $rport -eq "631" ]] && export CUPS_SERVER=localhost:$lport
    # ...
done

আদেশ সহকারে:

  • কোডটিতে চেক করার ক্ষেত্রে খুব বেশি ত্রুটি নেই
  • পরিবেশ পরিবর্তনের ফলে থ্রেড সম্পর্কিত সমস্যা হতে পারে, প্যাম থ্রেড ব্যবহার করে, আমি সমস্যা আশা করি না তবে আমি এটি পরীক্ষা করে দেখিনি
  • sshবর্তমানে * স্থানীয়: পোর্ট: রিমোট: পোর্ট * ফর্মটির সম্পূর্ণ ফরোয়ার্ডিং স্পষ্টভাবে লগ করে না (তবে প্রয়োজনে debug1বার্তাগুলির আরও বিশ্লেষণ ssh -vপ্রয়োজন হলে), তবে আপনার ব্যবহারের ক্ষেত্রে এটির দরকার নেই

অদ্ভুতভাবে যথেষ্ট যে ওপেনএসএইচ-এর কাছে পোর্ট ফরওয়ার্ডিং সম্পর্কিত তথ্য পুনরুদ্ধার করার উপায় আছে বলে মনে হয় না।

আপনি (আংশিকভাবে) পলায়ন সহ ইন্টারেক্টিভভাবে এটি করতে পারেন ~#, অদ্ভুতভাবে প্রয়োগগুলি শোনার চ্যানেলগুলির উপরে চলে যায়, এটি কেবল উন্মুক্ত (যেমন টিসিপি ESTABLISHED) তালিকাভুক্ত করে এবং এটি কোনও ক্ষেত্রে কার্যকর ক্ষেত্রগুলি মুদ্রণ করে না। দেখাchannels.c channel_open_message()

SSH_CHANNEL_PORT_LISTENERস্লটগুলির জন্য বিশদটি মুদ্রণের জন্য আপনি সেই ফাংশনটি প্যাচ করতে পারেন , তবে এটি কেবল আপনাকে স্থানীয় ফরোয়ার্ডিং দেয় ( চ্যানেলগুলি প্রকৃত ফরোয়ার্ডের মতো জিনিস নয় )। অথবা, আপনি বিশ্বব্যাপী optionsকাঠামো থেকে দুটি ফরোয়ার্ডিং টেবিল ডাম্প করতে প্যাচ করতে পারেন :

#include "readconf.h"
Options options;  /* extern */
[...]
snprintf(buf, sizeof buf, "Local forwards:\r\n");
buffer_append(&buffer, buf, strlen(buf));
for (i = 0; i < options.num_local_forwards; i++) {
     snprintf(buf, sizeof buf, "  #%d listen %s:%d connect %s:%d\r\n",i,
       options.local_forwards[i].listen_host,
       options.local_forwards[i].listen_port,
       options.local_forwards[i].connect_host,
       options.local_forwards[i].connect_port);
     buffer_append(&buffer, buf, strlen(buf));
}
snprintf(buf, sizeof buf, "Remote forwards:\r\n");
buffer_append(&buffer, buf, strlen(buf));
for (i = 0; i < options.num_remote_forwards; i++) {
     snprintf(buf, sizeof buf, "  #%d listen %s:%d connect %s:%d\r\n",i,
       options.remote_forwards[i].listen_host,
       options.remote_forwards[i].listen_port,
       options.remote_forwards[i].connect_host,
       options.remote_forwards[i].connect_port);
     buffer_append(&buffer, buf, strlen(buf));
}

এটি সূক্ষ্মভাবে কাজ করে, যদিও এটি কোনও "প্রোগ্রাম্যাটিক" সমাধান নয়, ক্লায়েন্ট কোডটি (তবুও এটি উত্সে এক্সএক্সএক্সএক্সএক্স পতাকাঙ্কিত নয়) তালিকাটি আপডেট করে যখন আপনি অন-দ্য ফ্লাইওয়ার্ড যুক্ত / সরান ( ~C)


সার্ভার (গুলি) যদি লিনাক্স হয় তবে আপনার আরও একটি বিকল্প রয়েছে, এটি আমি সাধারণত ব্যবহার করি, যদিও রিমোটের চেয়ে স্থানীয় ফরওয়ার্ডিংয়ের জন্য। lo127.0.0.1/8, লিনাক্সে আপনি স্বচ্ছভাবে যে কোনও ঠিকানার সাথে 127/8 এ আবদ্ধ করতে পারেন , তাই আপনি যদি অনন্য 127.xyz ঠিকানা ব্যবহার করেন তবে স্থির বন্দরগুলি ব্যবহার করতে পারেন, যেমন:

mr@local:~$ ssh -R127.53.50.55:44284:127.0.0.1:44284 remote
[...]
mr@remote:~$ ss -atnp src 127.53.50.55
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     0      128            127.53.50.55:44284                    *:*    

এটি বাধ্যতামূলক সুবিধাযুক্ত বন্দরগুলির সাপেক্ষে <1024, ওপেনএসএসএইচ লিনাক্স ক্ষমতা সমর্থন করে না এবং বেশিরভাগ প্ল্যাটফর্মগুলিতে একটি হার্ড-কোডেড ইউআইডি চেক থাকে।

বুদ্ধিমানের সাথে নির্বাচিত অক্টেটস (আমার ক্ষেত্রে এএসসিআইআই অর্ডিনাল মেমোনমিক্স) দিনের শেষে এই জগাখিচুড়ি কাটাতে সহায়তা করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.