จะสร้างผู้ใช้ SSH ที่ จำกัด สำหรับการส่งต่อพอร์ตได้อย่างไร


106

ændrük แนะนำการเชื่อมต่อแบบย้อนกลับสำหรับการเชื่อมต่อ SSH ที่ง่ายกับคนอื่น (สำหรับความช่วยเหลือระยะไกล) เพื่อให้สามารถใช้งานได้ผู้ใช้เพิ่มเติมจำเป็นต้องยอมรับการเชื่อมต่อ ผู้ใช้นี้จะต้องสามารถส่งต่อพอร์ตของเขาผ่านเซิร์ฟเวอร์ (เซิร์ฟเวอร์ทำหน้าที่เป็นพร็อกซี)

ฉันจะสร้างผู้ใช้ที่ถูก จำกัด ที่ไม่สามารถทำอะไรได้มากกว่าที่อธิบายไว้ข้างต้นได้อย่างไร

ผู้ใช้ใหม่จะต้องไม่สามารถ:

  • รันคำสั่งเชลล์
  • เข้าถึงไฟล์หรืออัพโหลดไฟล์ไปยังเซิร์ฟเวอร์
  • ใช้เซิร์ฟเวอร์เป็นพร็อกซี่ (เช่น webproxy)
  • เข้าถึงบริการในพื้นที่ซึ่งไม่สามารถเข้าถึงได้แบบสาธารณะเนื่องจากไฟร์วอลล์
  • ฆ่าเซิร์ฟเวอร์

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


คำตอบ:


166

TL; DR - ไปที่ด้านล่างของคำตอบ "การใช้ข้อ จำกัด "

การเพิ่มผู้ใช้ที่ถูก จำกัด ประกอบด้วยสองส่วน: 1. การสร้างผู้ใช้ 2. การกำหนดค่า SSH daemon (sshd)

การกำหนดค่า sshd

สถานที่ที่ดีที่สุดในการทำความรู้จักกับความเป็นไปได้ของ SSH คือการอ่านหน้าคู่มือที่เกี่ยวข้อง:

ไคลเอ็นต์ SSH สามารถดำเนินการได้ที่ไหน

ก่อนที่คุณจะสามารถ จำกัด บางสิ่งได้คุณต้องทราบคุณสมบัติของ SSH การคายผ่านหน้าเพจด้วยตนเองให้ผลตอบแทน:

  • เชลล์สั่งการทำงาน
  • อัพโหลดไฟล์ผ่าน sftp
  • การส่งต่อพอร์ต
    • ไคลเอ็นต์ส่งต่อพอร์ตที่ใช้ (un) ไปยังเซิร์ฟเวอร์
    • เซิร์ฟเวอร์ส่งต่อพอร์ตไปยังลูกค้า
    • เซิร์ฟเวอร์ส่งต่อพอร์ตของโฮสต์อื่นไปยังไคลเอนต์ (proxy-ish)
  • การส่งต่อ X11 (การแสดงการส่งต่อ)
  • ตัวแทนการตรวจสอบการส่งต่อ
  • การส่งต่อของอุปกรณ์อุโมงค์

จากส่วนการรับรองความถูกต้องของหน้าคู่มือของ sshd (8) :

หากไคลเอ็นต์พิสูจน์ตัวตนได้สำเร็จจะมีการป้อนไดอะล็อกสำหรับการเตรียมเซสชัน ในขณะนี้ไคลเอนต์อาจร้องขอสิ่งต่าง ๆ เช่นการ จัดสรรการหลอกส่งต่อการเชื่อมต่อ X11 การส่งต่อการเชื่อมต่อ TCP หรือการส่งต่อการเชื่อมต่อตัวแทนการรับรองความถูกต้องผ่านช่องทางที่ปลอดภัย

หลังจากนี้ลูกค้าทั้งขอเปลือกหรือการดำเนินการของคำสั่ง ด้านข้างจากนั้นเข้าสู่โหมดเซสชั่น ในโหมดนี้ทั้งสองข้างอาจส่งข้อมูลได้ตลอดเวลาและข้อมูลดังกล่าวจะถูกส่งต่อไปยัง / จากเชลล์หรือคำสั่งทางฝั่งเซิร์ฟเวอร์และเทอร์มินัลผู้ใช้ในฝั่งไคลเอ็นต์

ตัวเลือกสำหรับการ จำกัด คุณสมบัติ SSH

ไฟล์และตัวเลือกที่เปลี่ยนแปลงพฤติกรรมคือ:

  • ~/.ssh/authorized_keys - มีคีย์ที่ได้รับอนุญาตให้เชื่อมต่อซึ่งสามารถเลือกได้:
    • command="command"- คำสั่งที่จัดทำโดยผู้ใช้ (ถ้ามี) จะถูกละเว้น โปรดทราบว่าลูกค้าอาจระบุ TCP และ / หรือส่ง X11 จนกว่าพวกเขาจะไม่ได้รับอนุญาตอย่างชัดเจน โปรดทราบว่าตัวเลือกนี้ใช้กับการดำเนินการของเชลล์คำสั่งหรือระบบย่อย
    • no-agent-forwarding - ห้ามตัวแทนการรับรองความถูกต้องส่งต่อเมื่อใช้คีย์นี้สำหรับการรับรองความถูกต้อง
    • no-port-forwarding - ห้ามการส่งต่อ TCP เมื่อใช้คีย์นี้เพื่อการตรวจสอบสิทธิ์
    • no-X11-forwarding - "ห้าม X11 ส่งต่อเมื่อคีย์นี้ใช้สำหรับการตรวจสอบสิทธิ์"
    • permitopen="host:port" - จำกัด การส่งต่อพอร์ต 'ssh -L' บนโลคัลเพื่อให้สามารถเชื่อมต่อกับโฮสต์และพอร์ตที่ระบุเท่านั้น
  • ~/.ssh/environment- ไฟล์นี้จะถูกอ่านในสภาพแวดล้อมเมื่อเข้าสู่ระบบ (ถ้ามี) การประมวลผลสภาพแวดล้อมถูกปิดใช้งานโดยค่าเริ่มต้นและควบคุมผ่านตัวเลือก PermitUserEnvironment
  • ~/.ssh/rc - มีรูทีนการเริ่มต้นที่จะเรียกใช้ก่อนที่ไดเรกทอรีหลักของผู้ใช้จะสามารถเข้าถึงได้
  • /etc/ssh/sshd_config - ไฟล์การกำหนดค่าทั่วทั้งระบบ
    • AllowAgentForwarding - ระบุว่าอนุญาตให้ส่งต่อ ssh-agent (1) หรือไม่
    • AllowTcpForwarding
    • ForceCommand - "บังคับให้เรียกใช้งานคำสั่งที่ระบุโดย ForceCommand โดยไม่สนใจคำสั่งใด ๆ ที่จัดหาโดยไคลเอ็นต์และ ~ / .ssh / rc หากมีอยู่คำสั่งถูกเรียกใช้โดยใช้เปลือกเข้าสู่ระบบของผู้ใช้ที่มีตัวเลือก -c"
    • GatewayPorts - "ระบุว่าโฮสต์ระยะไกลได้รับอนุญาตให้เชื่อมต่อกับพอร์ตที่ส่งต่อให้กับลูกค้าหรือไม่โดยค่าเริ่มต้น sshd (8) ผูกการส่งต่อพอร์ตระยะไกลไปยังที่อยู่ลูปแบ็คซึ่งจะป้องกันไม่ให้โฮสต์ระยะไกลอื่น ๆ sshd นั้นควรอนุญาตให้ส่งต่อพอร์ตจากระยะไกลไปผูกกับที่อยู่ที่ไม่ใช่ลูปแบ็คดังนั้นจึงอนุญาตให้โฮสต์อื่นเชื่อมต่อได้ "
    • PermitOpen:

      ระบุปลายทางที่อนุญาตให้ส่งต่อพอร์ต TCP ข้อกำหนดการส่งต่อจะต้องเป็นหนึ่งในรูปแบบต่อไปนี้:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      การส่งต่อหลายอาจถูกระบุโดยแยกพวกเขาด้วยช่องว่าง สามารถใช้อาร์กิวเมนต์ของ 'any' เพื่อลบข้อ จำกัด ทั้งหมดและอนุญาตการร้องขอการส่งต่อใด ๆ คำขอส่งต่อพอร์ตทั้งหมดได้รับอนุญาต

    • PermitTunnel- ระบุว่าอนุญาตให้ส่งต่ออุปกรณ์ tun (4) หรือไม่ ค่าเริ่มต้นคือ 'ไม่'
    • X11Forwarding- ระบุว่าอนุญาตให้ส่งต่อ X11 ได้หรือไม่ ค่าเริ่มต้นคือ 'ไม่'

การใช้ข้อ จำกัด

การแก้ไขไฟล์กำหนดค่าทั้งระบบ/etc/ssh/sshd_configอนุญาตให้ใช้การกำหนดค่าแม้ว่าจะใช้การพิสูจน์ตัวตนด้วยรหัสผ่านหรือหาก~/.ssh/authorized_keysมีการลบข้อ จำกัด ในโดยไม่ตั้งใจ หากคุณแก้ไขค่าเริ่มต้นทั่วโลกคุณควรยกเลิกการใส่เครื่องหมายข้อคิดเห็นตัวเลือกตามนั้น

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

ตอนนี้เพิ่มผู้ใช้:

sudo useradd -m limited-user

ForceCommandคุณสามารถละเว้นตัวเลือกนี้ได้หากตั้งค่าเชลล์เป็นไม่ใช่แบบเชลล์/bin/false(หรือ/bin/true) เนื่องจาก/bin/false -c [command]จะไม่ทำอะไรเลย

ตอนนี้ไคลเอนต์สามารถเชื่อมต่อกับพอร์ต 62222 บนที่อยู่ลูปแบ็คของเซิร์ฟเวอร์ผ่าน SSH เท่านั้น (จะไม่ฟังที่อยู่ IP สาธารณะ)

การปิดใช้งานAllowTcpForwardingจะไม่อนุญาตให้ใช้-Rดังนั้นจึงเป็นการเอาชนะการใช้บัญชีที่ถูก จำกัด ดังกล่าวสำหรับการส่งต่อพอร์ตเดียว PermitOpen localhost:62222สมมติว่าพอร์ต 62222 บนเซิร์ฟเวอร์นั้นไม่เคยใช้งานเพราะลูกค้าสามารถเชื่อมต่อกับมันได้อย่างมีความสุขและฟังมันเช่นกัน

หากอนุญาตให้ส่งต่อ TCP ในการกำหนดค่าทั้งระบบและการตรวจสอบความถูกต้องด้วยรหัสผ่านคุณสามารถใช้การตั้งค่าสำหรับแต่ละคีย์ได้เช่นกัน แก้ไข~/.ssh/authorized_keysและเพิ่มตัวเลือกถัดไปก่อนหน้าssh-(ด้วยช่องว่างระหว่างตัวเลือกและssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

ตรวจสอบ

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

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

ข้อสรุป

รายการตรวจสอบ: ผู้ใช้ SSH ไม่สามารถ:

  • รันคำสั่งเชลล์ - เสร็จสิ้น
  • เข้าถึงไฟล์หรืออัพโหลดไฟล์ไปยังเซิร์ฟเวอร์ - ทำ
  • ใช้เซิร์ฟเวอร์เป็นพร็อกซี (เช่น webproxy) - เสร็จสิ้น
  • เข้าถึงบริการในพื้นที่ซึ่งไม่สามารถเข้าถึงได้แบบสาธารณะเนื่องจากไฟร์วอลล์ - บางส่วนลูกค้าไม่สามารถเข้าถึงพอร์ตอื่นนอกเหนือจาก 62222 แต่สามารถฟังและเชื่อมต่อกับพอร์ต 62222 บนเซิร์ฟเวอร์
  • ฆ่าเซิร์ฟเวอร์ - เสร็จสิ้น (โปรดทราบว่าการตรวจสอบเหล่านี้จะ จำกัด อยู่ที่เซิร์ฟเวอร์ SSH หากคุณมีบริการที่มีช่องโหว่อื่น ๆ บนเครื่อง

3
เพื่อให้ใช้งานได้บัญชีที่เพิ่มโดยuseraddจะต้องถูกปลดล็อค ที่สามารถทำได้โดยการเปลี่ยนรหัสผ่านใน/etc/shadowโดย asteric ( *) sudo passwd limited-userหรือโดยการตั้งค่ารหัสผ่านโดยใช้
Lekensteyn

2
SFTP ทำงานได้เนื่องจากเซิร์ฟเวอร์ SSH เรียกใช้sftp-serverคำสั่ง ด้วยForceCommandคำสั่งนี้จะไม่ถูกดำเนินการอีกต่อไป
Lekensteyn

2
ยังมีประโยชน์เป็นตัวเลือกในfrom= authorized_keysอนุญาตให้คุณ จำกัด การใช้คีย์ไปยังแหล่งที่มาด้วยที่อยู่ IP หรือชื่อโฮสต์เฉพาะ ตัวอย่างfrom="1.1.1.1"หรือfrom="10.0.0.?,*.example.com". โปรดดูส่วน "AUTHORIZED_KEYS FILE FORMAT" ในหน้า man ( linux.die.net/man/8/sshd ) สำหรับตัวเลือกที่ได้รับอนุญาตทั้งหมด
Donn Lee

2
"AllowTcpForwarding local" ห้ามส่งต่อระยะไกล (ฉันไม่รู้ว่ามันมีอยู่หรือไม่เมื่อคำตอบนี้ถูกเขียนขึ้น)
Simon Sapin

1
โปรดทราบว่านี้ได้รับการทำลายโดยการเชื่อมต่อ SSH ถาวรดังนั้นคุณไม่ควรมีสิ่งที่ต้องการHost * ControlMaster autoของคุณในไฟล์เมื่อเชื่อมต่อกับ~/.ssh/config ssh -Nหากคุณต้องการใช้ให้ใช้ssh -N -o ControlMaster=no
nh2

3

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

  • เพิ่มผู้ใช้ตามปกติ ('adduser' หรือเครื่องมืออื่น ๆ )

  • สร้างผู้ใช้. ssh dir และ. ssh / authorized_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • ปิดใช้งานการเข้าถึงรหัสผ่านของบัญชีนี้
your_user $ sudo usermod --lock ssh_forwarder

ตอนนี้วิธีเดียวที่ผู้ใช้สามารถเข้าสู่ระบบของคุณคือการเข้าถึงคีย์ ssh ที่เหมาะสมและ ssh จะเรียกใช้ "/ bin / bash -c 'อ่าน a" สำหรับพวกเขาไม่ว่าพวกเขาจะพยายามเรียกใช้ 'read a' จะอ่านจนกว่าจะถึงบรรทัดใหม่จากนั้นเชลล์จะออกดังนั้นผู้ใช้จะต้องกด 'Enter' เพื่อฆ่าการเชื่อมต่อ

มีสิ่งอื่น ๆ อีกมากมายที่คุณสามารถทำได้ใน 'command =' ดูman authorized_keysและค้นหา 'คำสั่ง' สำหรับข้อมูลเพิ่มเติม

หากคุณไม่ชอบความจริงที่ว่าการกดปุ่ม Enter เป็นการฆ่าการเชื่อมต่อคุณสามารถใช้สิ่งต่อไปนี้สำหรับรายการ 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

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

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

สิ่งนี้ควรใช้ทรัพยากรน้อยมากและไม่มีสิ่งใดที่จะผิดพลาดในสคริปต์นั้นซึ่งจะไม่สิ้นสุดในการยกเลิกเชลล์

sleep 1h; echo You have been here too long. Good bye.

ฉันไม่เห็นว่าคุณอนุญาตให้ผู้ใช้ส่งต่อรีโมต ( ssh -R) แต่ จำกัด ได้อย่างไร ( ssh -L) บางทีอาจใช้ 'permopen' Googlingไม่ค่อยมีประโยชน์ ก็ดูเหมือนว่าบางสิ่งบางอย่างเช่น 'ไม่มีพอร์ตการส่งต่อ permitremoteopen = 10001' ssh -R 6901:localhost:6901จะมีประโยชน์ในการช่วยให้

นี่คือวิธีการแก้ปัญหา สามารถปรับปรุงได้อย่างแน่นอนที่สุดและการเปิดพอร์ตระยะไกลใด ๆ ควรได้รับการพิจารณา หากเป้าหมายของฉันคืออนุญาตให้คุณยายของฉันเชื่อมต่อกับ LAN ของฉันเพื่อให้ฉันสามารถใช้ vnc เพื่อดูหน้าจอของเธอและการเข้าถึงปุ่มเหล่านั้นถูก จำกัด ไว้ที่เธอฉันเองจะรู้สึกปลอดภัยพอสมควร ถ้านี่คือสำหรับองค์กรการตรวจสอบอย่างละเอียดจะมีความจำเป็น สิ่งหนึ่งที่ควรระวังคือไม่ได้ร้องขอเชลล์เลยดังนั้นรหัส 'command =' จึงไม่ทำงานssh -N

กลไกอื่น ๆ ที่อาจมีความปลอดภัยมากกว่าอาจรวมถึงการสร้างเชลล์แบบกำหนดเองสำหรับผู้ใช้


3
นี่ดูเหมือนแฮ็คมากไม่จำเป็นต้องมีเชลล์เพราะไม่จำเป็นต้องเรียกใช้คำสั่ง ดูหน้าคู่มือของsshสำหรับ-Nตัวเลือก ต้องมีวิธีที่สะอาดกว่านี้ในการทำสิ่งนี้ให้สำเร็จ
Lekensteyn

นั่นเป็นเรื่องจริง ฉันหวังว่าจะเห็นโซลูชันที่สะอาดกว่านี้เช่นกัน ฉันคิดว่า authorized_keys ร่วมกับการไม่ส่งต่อพอร์ตจะเป็นทางออกที่ดีถ้ามีตัวเลือก 'อนุญาตสิทธิ์การใช้งาน'
ผิด

ฉันทำการวิจัยอีกครั้ง (ดูด้านบน) เนื่องจากssh -Nไม่ได้ดำเนินการคำสั่งเลยจึงไม่มีปัญหาที่command="something"ปิดเซสชัน
Lekensteyn

ฉันพลาดอะไรไปรึเปล่า? ดูเหมือนว่าchsh ssh_forwarder -s /bin/false มันคือทั้งหมดที่ใช้
typelogic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.