ส่งต่อพอร์ตโลคัลหรือไฟล์ซ็อกเก็ตไปยังไฟล์ซ็อกเก็ตระยะไกล


24

คำถามอย่างรวดเร็ว - ฉันใช้งานกล่องลินุกซ์สองช่องตัวหนึ่งซึ่งเป็นเดสก์ท็อปของฉันและอีก VPS เพื่อเหตุผลด้านความปลอดภัยในส่วน VPS ฉันเลือกใช้การเชื่อมต่อซ็อกเก็ตกับ MySQL ( /var/run/mysqld/mysql.sock) ฉันรู้ว่าฉันสามารถขุดอุโมงค์แบบนี้ได้: ssh -L 3307:127.0.0.1:3306 user@site.comถ้าฉันตั้งค่าเซิร์ฟเวอร์ sql ระยะไกลเพื่อฟังบนพอร์ตบางตัว แต่สิ่งที่ฉันอยากรู้คือฉันสามารถทำอะไรได้บ้าง: ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sockดังนั้นการขุดอุโมงค์สองซ็อกเก็ตซึ่งต่างจากสองพอร์ต

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

(และใช่ฉันรู้ว่า TCP จะง่ายขึ้น)


หากเหตุผลที่คุณไม่ต้องการใช้ TCP ในกล่อง mySQL นั้นเป็นเพราะความกังวลด้านความปลอดภัย (เช่นการโจมตีจากระยะไกล ฯลฯ ) คุณสามารถเลือกไฟร์วอลล์ได้ทั้งสองอย่างและถ้านั่นไม่ดีพอให้ mySQL ฟังเพียง 127.0.0.1 สำหรับการเชื่อมต่อ TCP จากนั้นคุณสามารถทันเนลผ่าน SSH ได้อย่างง่ายดาย ถ้าไม่ฉันสนับสนุนโซลูชัน socat ด้านล่าง
Mattias Ahnberg

lwn.net/Articles/609321 OpenSSH 6.7 จะนำการส่งต่อซ็อกเก็ต
Hubbitus

@Hubbitus คุณลักษณะนี้มีให้ใช้งานในตอนนี้ถ้าเป็นเช่นนั้นคุณสามารถให้คำตอบตัวอย่างได้หรือไม่?
CMCDragonkai

ความคิดเห็นนั้นอยู่ในรูปแบบคำตอบ แต่เปลี่ยนเป็นความคิดเห็นโดยใครบางคน และฉันเห็นตอนนี้คุณแนะนำคำตอบด้านล่างแล้ว
Hubbitus

คำตอบ:


35

ส่งต่อซ็อกเก็ตท้องถิ่นตามความต้องการ

  • ตั้งค่าการรับรองความถูกต้องของคีย์สาธารณะ SSH
  • ติดตั้งsocatที่ปลายทั้งสอง
  • สร้างไดเรกทอรีในเครื่องสำหรับซ็อกเก็ตของคุณเข้าถึงผู้ใช้รายอื่นไม่ได้
export SOCKET_DIR=~/.remote-sockets
mkdir -p $SOCKET_DIR
socat "UNIX-LISTEN:$SOCKET_DIR/mysqld.sock,reuseaddr,fork" \
EXEC:'ssh user@server socat STDIO UNIX-CONNECT\:/var/run/mysqld/mysqld.sock'

แล้วก็

mysql -S $SOCKET_DIR/mysqld.sock -u mysqluser -p

ถูกขโมยจากการส่งต่อโดเมนซ็อกเก็ต unix ด้วย ssh และ socat


นี่เป็นสิ่งที่ยอดเยี่ยมและควรเป็นคำตอบที่ได้รับการยอมรับ
John Smith ทางเลือก

32

ในเวลาสูงเมื่อถามคำถามมันเป็นไปไม่ได้จริงๆ แต่เป็นไปได้ในปัจจุบัน

คุณสามารถทำได้ทั้ง: UNIX => TCP และ UNIX => การส่งต่อ UNIX

ตัวอย่างเช่น:

ssh \
  -R/var/run/mysql.sock:/var/run/mysql.sock \
  -R127.0.0.1:3306:/var/run/mysql.sock \
  somehost

เป็นไปได้ตั้งแต่ OpenSSH 6.7


1
ฉันจัดการเพื่อส่งต่อซ็อกเก็ตท้องถิ่นของฉันกับซ็อกเก็เซิร์ฟเวอร์ระยะไกลโดยใช้ข้างต้นและลูกค้าวิ่งระยะไกลนักเทียบท่า (มันสามารถทำได้โดย SSH โดยตรง แต่ที่เป็นความสนุกใน :) ว่าssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
sdkks

11

ผมไม่เคยทำแบบนี้ แต่ผมจะลองกับsocat อาจจะชอบ:

ssh xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:localhost:9999 UNIX-CONNECT:/var/run/mysqld/mysql.sock"
socat UNIX-LISTEN:/path/to/local/socket TCP:localhost:9999

อีกครั้งฉันไม่เคยทำอะไรแบบนี้


ฉันจะปล่อยมันและบอกให้คุณรู้ว่ามันเป็นอย่างไร ฉันใช้ tcp-based implementation

ฉันไม่สามารถทำให้มันทำงานได้ในขณะนี้ แต่ +1 สำหรับความคิดฉันชอบมัน ฉันจะแจ้งให้คุณทราบหากฉันแก้ไข

+1 ดูเหมือนว่ามีประโยชน์
วอร์เนอร์

5

ไม่จำเป็นต้องใช้ socat อีกต่อไปตั้งแต่ ssh 6.7 คุณสามารถส่งต่อซ็อกเก็ตโดเมน unix ได้โดยตรงเช่น:

ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

ข้อมูลเพิ่มเติม: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160


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

ส่งต่อซ็อกเก็ตไปยังเครื่องเดียวกัน แต่ไดเรกทอรีที่แตกต่างกันควบคุมโดยผู้ใช้ที่แตกต่างกันใช้ sshd เพื่อตรวจสอบสิทธิ์การเข้าถึง? usecase ของคุณคืออะไร?
CMCDragonkai

การอนุญาต / การเข้าถึงไดเรกทอรีไม่มีปัญหา แต่daemon ที่เฉพาะเจาะจงจะลดความพยายามในการเชื่อมต่อใด ๆ ที่ทำโดยผู้ใช้ในกลุ่มใดกลุ่มหนึ่ง (ควรจะป้องกันมือใหม่ที่สับสน) การใช้ ssh อนุญาตให้ผู้ใช้เหล่านั้นเชื่อมต่อ (ผ่านซ็อกเก็ตที่รับสัญญาณ) ราวกับว่าพวกเขาเป็นผู้ใช้ที่ไม่ได้อยู่ในกลุ่มนั้นและด้วยเหตุนี้จึงไม่ถูกตัดการเชื่อมต่อ
Warbo

น่าสนใจและตลกดีที่คุณหมายถึง nix-daemon ฉันกำลังพูดถึงประเด็นที่เกี่ยวข้อง ฉันสงสัยว่าทำไม nix-daemon กำลังทิ้งการเชื่อมต่อกับผู้ใช้ในกลุ่มใดกลุ่มหนึ่ง นี่เป็นสิ่งที่กำหนดค่าความปลอดภัยหรือไม่? หรือเกี่ยวข้องกับ: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai

ตามข้อความการส่งข้อความเพื่อป้องกันการใช้งานโดยไม่ตั้งใจ ฉันนำมันมาที่นี่
Warbo

2

การแก้ไขอีกคำตอบของ @mpontes '/ @ javier นั้น

ssh user@remoteserver -L 9999:localhost:9999 'socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

ทำความสะอาด

ssh user@remoteserver -L 9999:localhost:9999 '
  socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock&
  pid=$!
  trap "kill $pid" 0
  while echo -ne " \b"; do
    sleep 5
  done
'

ข้อดี

  1. ทำงานบน openssh ก่อนหน้า 6.7 (เช่น CentOS 7)
  2. ฆ่า socat เมื่อยกเลิก ssh แทนที่จะต้อง re-ssh เข้าไปในรีโมตเซิร์ฟเวอร์
  3. อนุญาตการลงชื่อเข้าใช้แบบสาธารณะ ssh (ไม่เหมือนกับโซลูชัน ijk)

ลักษณะ

  1. เนื่องจาก-fไม่ได้ใช้ตัวเลือกคุณสามารถใช้พับลิกคีย์และรันในพื้นหลังผ่าน&หรือคุณสามารถล็อกอินแบบโต้ตอบและใช้ Ctrl + Z และใช้แบบเดียวกัน$!เพื่อเก็บ pid

ข้อเสีย

  1. ไม่สามารถใช้-fตัวเลือก ssh ได้อย่างง่ายดายเนื่องจากคุณจะสูญเสีย pid ของ ssh ด้วยวิธีนั้น วิธีนี้อาศัยการทำงานในเบื้องหน้าและ Ctrl + C เพื่อฆ่า
  2. ไกลยิ่งซับซ้อน

คำอธิบาย

  • socat ...& - เรียกใช้ socat ในพื้นหลังบนเซิร์ฟเวอร์ระยะไกล
  • pid=$! - เก็บ pid
  • trap kill\ $pid 0- ทำงานkill $pidเมื่อสิ้นสุดการทุบตี
  • while :; sleep... - นั่งในวงวนไม่สิ้นสุด
  • echo -ne \ \b- พื้นที่ Echo ตามด้วย backspace สิ่งนี้จะล้มเหลวทันทีที่ยกเลิกการเชื่อมต่อ ssh ด้วย a sleep 5หมายความว่าsocatสามารถทำงานได้นานถึง 5 วินาทีหลังจาก ssh

หมายเหตุ:การทดสอบจริงโดยใช้นักเทียบท่าพอร์ต2375, /var/run/docker.sockและตัวแปรสภาพแวดล้อมDOCKER_HOST='tcp://localhost:2375'แต่ควรจะทำงานสำหรับ MySQL เหมือนกันทั้งหมด

ปรับปรุง

ใช้การควบคุม SSHคุณสามารถใช้การ-fตั้งค่าสถานะโดยใช้วิธีของฉันเพียงเพิ่มการตั้งค่าสถานะต่อไปนี้

-f -o ControlPath=~/.ssh/%C -o ControlMaster=auto

และคุณจะได้รับ

ssh -f -o ControlPath=~/.ssh/%C -o ControlMaster=auto user@remoteserver -L 9999:localhost:9999 'set -m; socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

ตอนนี้คุณสามารถยุติเซสชันที่ควบคุมทั้งหมดโดยใช้

ssh -o ControlPath=~/.ssh/%C -O exit remoteserver

-oตัวเลือกที่สามารถบันทึกไว้ในของคุณ.ssh/configแฟ้มหรือคุณสามารถใช้ -S แทน ( แต่คุณจะยังคงจำเป็น-o ControlMaster)


ฉันใช้สคริปท์ภายในคอนเทนเนอร์ Docker เพื่อปรับใช้โค้ดกับโฮสต์อื่น ๆ ตรรกะการเชื่อมต่อของคุณน่าอัศจรรย์ แต่จะสิ้นสุดลงเมื่อเซสชัน bash สิ้นสุดลง นี้จะช่วยป้องกันของฉันจากการเรียกการติดตั้งอุโมงค์ตามมาด้วยdocker run ... connect.sh docker run ... deploy.shฉันพยายามnohup, &และdisownแต่พวกเขาดูเหมือนจะแบ่งsocatโดยการปิดและเรียกstdout killมีความคิดเห็นใดสำหรับการปรับแต่งเพื่อสนับสนุนกรณีนี้ (เช่นยังคงปิดเมื่อ SSH ทำ แต่รอดชีวิตจากการถูกปฏิเสธ)?
claytond

ตกลง. ใช้งานได้จริง (w / -fและ& disown) ในเทอร์มินัล เห็นได้ชัดว่าปัญหาถูกสร้างขึ้นโดยสคริปต์ "wrapper" ฉันยินดีต้อนรับการป้อนข้อมูล แต่กำลังดูคำถาม & คำตอบที่เหมาะสมกว่าตอนนี้
claytond

@claytond ไม่แน่ใจว่าสิ่งที่คุณกำลังทำ แต่ใช่คำสั่งอื่น ๆ ทั้งหมดจะถูกยกเลิกเมื่อ pid 1 ของคอนเทนเนอร์สิ้นสุดลงสิ่งที่ฉันมักจะทำในสถานการณ์สคริปต์ของคุณปรับใช้คือใช้คำสั่ง "deploy" และเขียน entrypoint สำหรับคอนเทนเนอร์ของฉัน อิมเมจที่จะพูดว่า "ถ้า $ 1 (คำสั่ง) == deploay จากนั้น" รันคำสั่ง ssh และคำสั่งการนำไปใช้และจากนั้นจบซึ่งจะปิดการเชื่อมต่อ ssh คุณยังสามารถdocker run ... connect.shและdocker exec {container name/id} deploy.shเพื่อให้พวกเขาเล่นด้วยกัน
แอนดี้

คุณถูก. จริง ๆ แล้วฉันใช้execกับrunภาชนะแล้วและท่อ SSH ก็ไม่หายหลังจากexecจบ ฉันชี้แจงว่ามันเป็นเพราะการเล่นโวหารที่มีวิธีการดำเนินการสคริปต์ ถ้าผมย้ายไปเรียกร้องให้มันเป็นสคริปต์เองและเรียกว่ามันมีชีวิตอยู่เสร็จสิ้นการที่nohup <script.sh> & disown exec
Claytond

1

อธิบายคำตอบของ Javier ได้ดีสำหรับฉัน:

ssh -f xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

คุณต้องการforkเพื่อที่จะสามารถเชื่อมต่อได้หลายครั้งโดยไม่ต้องเสียค่า socat เมื่อคุณปิดการเชื่อมต่อครั้งแรก นอกจากนี้วิธีที่ socat ช่วยให้คุณระบุที่อยู่ที่จะผูกไว้ผ่านbindตัวเลือกไม่ใช่ที่อยู่ก่อนพอร์ต

หลังจากนี้เพียงเชื่อมต่อlocalhost:9999ตามปกติตามที่คุณต้องการ จากนั้นเพื่อฉีกอุโมงค์:

ssh -f xxx@yyy.zzz "killall socat"

(หรือสิ่งที่คล้ายกันคุณสามารถทำสิ่งที่ซับซ้อนมากขึ้นที่เกี่ยวข้องกับการรักษา PID ของ socat)


1

ใช่คุณสามารถใช้ socat ได้

ก่อนอื่นให้ทำการทันเนล TCP กับ SSH จากนั้นใช้ socat ดังนี้:

socat unix-Listen: /var/run/mysqld/mysqld.sock,fork,unlink-early tcp: 127.0.0.1: 3306

จากนั้นให้สิทธิ์กับซ็อกเก็ตที่สร้างขึ้นใหม่ (chmod 777 อาจเป็น)


สิ่งนี้เป็นไปได้ตั้งแต่ OpenSSH 6.6
ysdx

3
chmod 777: ไม่ไม่ไม่ไม่ไม่! chmod 777ไม่เคยทำงานเลยทีเดียว มันไม่จำเป็นต้องใช้จริง! ไม่แม้แต่สำหรับ "วัตถุประสงค์การทดสอบ" หากไฟล์สามารถอ่านได้แสดงว่าสามารถอ่านได้ หากมันสามารถเขียนได้โดยuserหรือgroupที่จำเป็นต้องเขียนไปมันก็สามารถเขียนได้ มีความจำเป็นอย่างยิ่งที่จะต้องให้สิทธิ์การเขียนแก่ทุกคนและการลืมchmodกลับไปสู่สิ่งที่มีสตินั้นเป็นวิธีการที่แฮ็คข้ามชาติ อย่าทำอย่างนั้น เคย ผมเขียนการแนะนำของสิทธิ์ยูนิกซ์ โปรดอ่านมัน!
Martin Tournoij
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.