Score:2

เข้าถึงแอปพลิเคชันของ WSL2 Ubuntu บนเครือข่ายของเครื่องโฮสต์

ธง tr

ฉันใช้แอพใน WSL2 ซึ่งมีการกระจายเป็น Ubuntu 20.04 ฉันสามารถเข้าถึงแอปพลิเคชันในเบราว์เซอร์ windows ด้วย IP ของ Ubuntu

ตอนนี้ฉันต้องการเข้าถึงแอปพลิเคชันนี้บนเครือข่ายของฉัน (ฉันหมายถึงในเครือข่ายสำนักงานของฉันบนเครื่องอื่น)

ฉันเข้าใจว่า IP ของอูบุนตูใช้ได้เฉพาะกับเครื่องโฮสต์เท่านั้น ฉันจะทำให้ผู้อื่นในเครือข่ายของฉันใช้งานได้อย่างไร

เราจะทำสิ่งนี้ได้อย่างไร? กรุณาช่วย.

hr flag
WSL หรือ WSL2? ขั้นตอนดูเหมือนจะแตกต่างออกไป ดูตัวอย่าง [การส่งต่อพอร์ต WSL](https://dev.to/vishnu12/wsl-port-forwarding-2e22)
tr flag
เป็น WSL2 แต่ตัวอย่างข้างต้นใช้สำหรับ WSL โปรดแก้ไขฉันหากผิด
hr flag
ฉัน *คิดว่า* เป็นกรณีที่คุณไม่จำเป็นต้องทำอะไรกับ WSL (ควร "ใช้งานได้") ในขณะที่ WSL2 คุณต้องตั้งค่าการส่งต่อพอร์ตตามที่อธิบายไว้ในบทความที่เชื่อมโยง แต่มาดูกันว่าคุณจะได้คำตอบอะไรบ้าง
NotTheDr01ds avatar
vn flag
@steeldriver คุณถูกต้อง ฉันจะเพิ่มรายละเอียดมากขึ้นในคำตอบของฉัน ฉันไม่ได้ทำสิ่งนี้มาระยะหนึ่งแล้ว แต่ฉันมีแนวคิดใหม่สองสามข้อที่จะลองตั้งแต่ครั้งล่าสุดที่ฉันจะเสนอว่าได้ผลหรือไม่ การส่งต่อพอร์ตจะใช้งานได้ แต่โพสต์นั้นดูเหมือนจะซับซ้อนเกินไป ฉันหวังว่าจะสามารถเสนอสิ่งที่มีประสิทธิภาพมากกว่านี้ แต่เราจะได้เห็นกัน
hr flag
@ NotTheDr01ds ยอดเยี่ยม - ตั้งหน้าตั้งตารออ่าน!
NotTheDr01ds avatar
vn flag
และ @Raushan เพื่อความชัดเจน เอกสารที่ steeldriver เชื่อมโยงนั้นมีไว้สำหรับ WSL2 ตามที่ระบุไว้ด้านบน WSL1 ไม่ต้องการอะไรแบบนั้น แต่อีกครั้งอย่าทำตามเอกสารนั้น มันจะใช้งานได้ แต่ฉันมีวิธีแก้ไข (ซึ่งตอนนี้ฉันได้รับการยืนยันแล้ว) ว่าฉันเขียนเป็นคำตอบที่ฉันเชื่อว่าง่ายกว่า
Score:3
ธง vn

คำตอบสั้น ๆ สำหรับ WSL1:

กำหนดค่ากฎไฟร์วอลล์ของคุณเพียงครั้งเดียว และทุกอย่างควร "ใช้งานได้" นี่เป็นวิธีที่ง่ายที่สุด

คำตอบสั้น ๆ สำหรับ WSL2:

เมื่อคุณกำหนดค่าต่างๆ อย่างถูกต้องแล้ว คุณสามารถเริ่มต้นการส่งต่อพอร์ตได้อย่างง่ายดายด้วยคำสั่งเดียวจาก Ubuntu/WSL2:

ssh -f -N -R 8080:localhost:8080 "$(ชื่อโฮสต์).local"

รายละเอียดเกี่ยวกับวิธีการกำหนดค่าอยู่ด้านล่าง ไม่จำเป็นต้องง่าย แต่ทั้งหมดนี้เป็นการตั้งค่าเพียงครั้งเดียว


(มาก) รายละเอียดเพิ่มเติม:

ตามที่ Steeldriver ระบุไว้ในความคิดเห็น WSL1 และ WSL2 ทำงานแตกต่างกันที่นี่

หมายเหตุด้านข้างเพียงเพื่อชี้แจงคำศัพท์ (เนื่องจากมีความแตกต่างกันเล็กน้อยในความคิดเห็น): "WSL" หมายถึงระบบย่อยเองซึ่งควบคุมทั้งสองเวอร์ชัน - WSL1 และ WSL2

หมายเหตุด้านข้าง 2 โปรดอย่าปล่อยให้ความยาวของโพสต์นี้ทำให้คุณตกใจ ฉันแค่ มาก รายละเอียด พิจารณาจาก ปัญหา Github ที่เกี่ยวข้อง มีมากถึง (ปัจจุบัน) 536 ความคิดเห็น ฉันคิดว่าฉันค่อนข้างรัดกุมเมื่อเปรียบเทียบ ;-)


WSL1

WSL1 เป็นกรณีการใช้งานที่ง่ายกว่าอย่างแน่นอน เนื่องจากเป็น "เลเยอร์การแปล" ระหว่าง Linux syscalls และเคอร์เนลของ Windows จึงใช้อินเทอร์เฟซเครือข่าย Windows "ของจริง" ด้วยเหตุนี้ คุณจึงสามารถเชื่อมต่อโดยตรงจากอุปกรณ์อื่นบนเครือข่ายไปยังพอร์ตใน WSL1

คุณน่าจะ ทำ ยังคงต้องการกฎไฟร์วอลล์อย่างไรก็ตาม ฉันจะครอบคลุมสิ่งนั้นในคำตอบ WSL2 เนื่องจากเป็นเรื่องปกติสำหรับทั้งสองอย่าง ดู ใหม่ NetFirewallRule คำสั่งในส่วน WSL2 เพียงเรียกใช้คำสั่งเดียว (ครั้งเดียว) สำหรับกฎไฟร์วอลล์

อย่างไรก็ตาม หากเว็บแอปของคุณไม่ต้องการ WSL2 (และส่วนใหญ่ต้องการ ไม่) โดยปกติแล้วการเรียกใช้จากอินสแตนซ์ WSL1 จะง่ายกว่ามาก (หรืออย่างน้อยก็เคยเป็น) นั่นคือสิ่งที่คนส่วนใหญ่จบลงด้วยการทำ ในทางกลับกัน ด้วยวิธี WSL2/SSH ใหม่ (อย่างน้อยสำหรับฉัน) ที่ฉันเสนอด้านล่าง มันไม่เจ็บปวดเท่าที่เคยทำใน WSL2 ผมจะปล่อยให้คุณเลือกทางไหน ณ จุดนี้ฉันคิดว่าทั้งสองจะใช้ได้เท่าเทียมกัน

หากคุณเลือกที่จะใช้ WSL1 ฉันขอแนะนำให้เก็บอินสแตนซ์ Ubuntu สองอินสแตนซ์ไว้ -- หนึ่งมี WSL1 และอีกอันมี WSL2 นั่นคือสิ่งที่ฉันทำ.

หากต้องการคัดลอกอินสแตนซ์ WSL2 ที่มีอยู่ของคุณไปยัง WSL1 ใหม่ ให้ออกจากอินสแตนซ์ที่มีอยู่และจาก PowerShell:

#ปรับเส้นทางฐานได้ตามต้องการ
$WSL_ROOT = "$env:USERPROFILE\WSL"
$WSL_IMAGE_NAME = "$(get-date -UFormat `"%Y-%m-%d`") Ubuntu Backup.tar"
mkdir -p "$WSL_ROOT\images"
mkdir -p "$WSL_ROOT\อินสแตนซ์\Ubuntu_WSL1"
ซีดี $WSL_ROOT
wsl -l -v
# ยืนยันชื่อการแจกจ่าย - หากไม่ใช่ "Ubuntu" ให้ปรับบรรทัดต่อไปนี้ตามต้องการ
wsl --export Ubuntu "$WSL_ROOT\images\$WSL_IMAGE_NAME"
wsl --import Ubuntu_WSL1 .\instances\Ubuntu_WSL1\ .\images\$WSL_IMAGE_NAME --version 1
wsl ~ -d Ubuntu_WSL1

ณ จุดนี้ คุณจะอยู่ในอินสแตนซ์ของ Ubuntu WSL1 แต่คุณจะถูกรูท เนื่องจาก WSL ไม่ "จำ" ชื่อผู้ใช้เริ่มต้นสำหรับ --นำเข้าอินสแตนซ์ ทำตาม "วิธีที่ 1" ของฉัน จากคำตอบนี้ เพื่อตั้งชื่อผู้ใช้เริ่มต้นของคุณ

ณ จุดนี้ คุณมีอินสแตนซ์ WSL Ubuntu สองอินสแตนซ์ หนึ่งอินสแตนซ์สำหรับ WSL1 (Ubuntu_WSL1) และอีกอันสำหรับ WSL2 (น่าจะเป็น อูบุนตู หรือบางที อูบุนตู-20.04). หากคุณใช้ Windows Terminal ระบบจะตรวจจับทั้งคู่และสร้างโปรไฟล์สำหรับการเปิดใช้งาน หรือคุณสามารถเปิดใช้งานด้วยตนเองได้ตลอดเวลา wsl ~ -d <ดิสโทรเนม>.

อีกทางเลือกหนึ่งคือการง่าย แปลง เป็น WSL1 และใช้เฉพาะ ขั้นตอนนี้คล้ายกับการคัดลอก เนื่องจากคุณยังคงต้องการสำรองข้อมูลอยู่ ออกจากอินสแตนซ์และจาก PowerShell อีกครั้ง:

#ปรับเส้นทางฐานได้ตามต้องการ
$WSL_ROOT = "$env:USERPROFILE\WSL"
$WSL_IMAGE_NAME = "$(get-date -UFormat `"%Y-%m-%d`") Ubuntu Backup.tar"
mkdir -p "$WSL_ROOT\images"
ซีดี $WSL_ROOT
wsl -l -v
# ยืนยันชื่อการแจกจ่าย - หากไม่ใช่ "Ubuntu" ให้ปรับบรรทัดต่อไปนี้ตามต้องการ
wsl --export Ubuntu "$WSL_ROOT\images\$WSL_IMAGE_NAME"
wsl --set-version อูบุนตู 1

ไม่จำเป็นต้องรีเซ็ตชื่อผู้ใช้เริ่มต้นในกรณีนี้


WSL2

WSL2 เริ่มซับซ้อนขึ้นมาก แม้ว่าจะมีลิงก์ในความคิดเห็นไปยังเอกสารเกี่ยวกับวิธีการทำ แต่เราจะชี้ให้คุณไปที่ ปัญหา Github ดั้งเดิมและความคิดเห็น ที่เริ่มคนมาแนวนี้จริงๆ

มีสองปัญหาจริงที่ต้องแก้ไขเพื่อให้สิ่งนี้ทำงานใน WSL2:

  • ประการแรก เครือข่าย WSL2 เป็นเครือข่ายเสมือน (จริง ๆ แล้วคือ Hyper-V vNIC) มันไม่ได้อยู่ใน "เครือข่ายสำนักงาน" ของคุณ ตามที่คุณระบุในคำถามของคุณ ก่อนอื่นคุณต้องมีวิธีบอกโฮสต์ Windows ให้กำหนดเส้นทางแพ็กเก็ตไปยังเครือข่ายเสมือน WSL2 ของคุณสำหรับพอร์ตนั้น

  • การส่งต่อนั้นซับซ้อนเนื่องจากที่อยู่เครือข่าย WSL2 เสมือนเปลี่ยนไปทุกครั้งที่รีบูต (หรือ wsl -- ปิดเครื่อง). นั่นหมายความว่า (อย่างน้อยด้วยวิธีที่บันทึกไว้ในความคิดเห็นและปัญหา Github) ที่คุณต้องทำซ้ำขั้นตอน:

    • ค้นหาที่อยู่ IP WSL2
    • การลบกฎไฟร์วอลล์เก่า
    • กำลังลบกฎการส่งต่อเก่า
    • การสร้างกฎไฟร์วอลล์ใหม่
    • การสร้างกฎการส่งต่อใหม่

... ทุกครั้งที่คุณรีบูต เจ็บอะไรนักหนาวะ!

ดังนั้นฉันจะเสนอสิ่งที่ฉันเชื่อว่าเป็นวิธีที่ง่ายกว่า คุณยังสามารถถอยกลับไปใช้วิธีอื่นได้หากต้องการ นี้มีบางอย่าง เล็กน้อย การตั้งค่าที่ซับซ้อน แต่ต้องทำเกือบทั้งหมดเท่านั้น ครั้งหนึ่ง.

วิธีนี้ใช้ SSH เพื่อให้การส่งต่อพอร์ต เนื่องจากสิ่งนี้เริ่มต้นจาก WSL2-end จึงมีข้อดีหลายประการ:

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

  • สิ่งสำคัญที่สุดคือไม่ต้องการที่อยู่ IP ของ WSL2 เพื่อหลีกเลี่ยงความจำเป็นในการทำ 4 ขั้นตอนข้างต้นทุกครั้งที่คุณรีบูต

เอาล่ะ ไปเลย ประการแรก มีการตั้งค่า "ครั้งเดียว":

  • เปิดใช้งานเซิร์ฟเวอร์ Windows OpenSSH คุณสามารถปฏิบัติตาม Microsoft คำแนะนำแต่ฉันจะสรุปที่นี่ เริ่มต้นด้วยการเปิดพรอมต์ PowerShell ในฐานะผู้ดูแลระบบ จากนั้น:

    เพิ่ม WindowsCapability - ออนไลน์ - ชื่อ OpenSSH.Client~~~~0.0.1.0
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
    ตั้งค่าบริการ - ชื่อ sshd -StartupType 'อัตโนมัติ'
    

    สิ่งนี้ควรสร้างกฎการส่งต่อ SSH โดยอัตโนมัติ อีกครั้งดูที่ เอกสาร หากคุณประสบปัญหาใด ๆ

  • แก้ไข C:\ProgramData\ssh\sshd_config และตรวจสอบให้แน่ใจว่า GatewayPort ใช่ ไม่ได้แสดงความคิดเห็น ฉันเชื่อว่ามันถูกปิดใช้งานโดยค่าเริ่มต้น

  • ย้อนกลับไปใน PowerShell ผู้ดูแลระบบของคุณ ให้เรียกใช้:

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

    New-NetFirewallRule -DisplayName 8080 -Direction Inbound -LocalPort 8080 -Protocol TCP -Action Allow -Profile ส่วนตัว
    

    นี้:

    • อนุญาตการรับส่งข้อมูล TCP ขาเข้า
    • บนพอร์ต 8080
    • จากอุปกรณ์บนเครือข่ายส่วนตัว

    หากตั้งค่าเครือข่ายของคุณ สาธารณะ, วาง - โปรไฟล์ส่วนตัว

  • ออกจากผู้ดูแลระบบ PowerShell

เมื่อหลีกทางให้ ทุกอย่างก็เข้าที่ ในการเริ่มต้นการส่งต่อ ณ จุดนี้ ให้ดำเนินการต่อไปนี้จาก Ubuntu/WSL2:

ssh -f -N -R 8080:localhost:8080 "$(ชื่อโฮสต์).local"

ใช้ของคุณ หน้าต่าง ชื่อผู้ใช้และรหัสผ่าน

ณ จุดนี้ คุณควรเข้าถึงเว็บแอปของคุณจากคอมพิวเตอร์เครื่องอื่น (หรือโทรศัพท์ หรืออะไรก็ตาม) บนเครือข่ายสำนักงานเดียวกัน

คำอธิบาย:

  • เชื่อมต่อ จาก อูบุนตู/WSL2
  • ถึง OpenSSH Server ที่เราตั้งค่าไว้
  • ใช้ "$(ชื่อโฮสต์).local" ซึ่ง (ควร) ค้นหาชื่อ DNS ที่ถูกต้องเสมอผ่าน mDNS (คำอธิบายใน คำตอบนี้.
  • ไม่ได้จัดสรรเทอร์มินัล (-น) และทำงานในพื้นหลัง (-ฉ) หลังจากร้องขอข้อมูลรับรองการเข้าสู่ระบบ
  • มันบอกโฮสต์ SSH ระยะไกล (Windows) ให้ส่งต่อการรับส่งข้อมูลที่ได้รับบนพอร์ต 8080 ไปยังพอร์ตท้องถิ่น (WSL2) 8080
  • เพราะเราระบุ GatewayPort ใช่ ในการกำหนดค่าเซิร์ฟเวอร์ หมายความว่าจะขยายการส่งต่อไปยัง อื่นๆ โฮสต์บนเครือข่ายด้วย
Score:0
ธง cn

ในขณะที่ คำตอบ ให้บริการโดย @น็อทเดอะดร01ds ถูกต้องและให้ข้อมูลมาก นี่เป็นวิธีแก้ปัญหาอื่นที่ใช้ PowerShell ขับเคลื่อนโดย Bash บน Ubuntu บน WSL :)

เพิ่มฟังก์ชันต่อไปนี้ที่ด้านล่างของคุณ ~/.bashrc ไฟล์. หากคุณมีอินสแตนซ์ WSL มากกว่าหนึ่งรายการ คุณสามารถทำได้สำหรับแต่ละอินสแตนซ์

เปลี่ยนค่าสำหรับ wsl_port และ win_port ตามความต้องการของคุณ เลือกเปลี่ยนค่าของ win_ip หากคุณต้องการฟังที่อินเทอร์เฟซเครือข่ายบางอย่างแทนอินเทอร์เฟซที่มีอยู่ทั้งหมด ซึ่งเป็นความหมายของ 0.0.0.0.

wsl_win_proxy() {
    wsl_ip="$(เส้นทาง ip | grep -oP '^.*src \K[0-9\.]+')"
    wsl_port="8080"

    win_ip="0.0.0.0"
    win_port="8080"

    rule_name="ขาเข้า TCP ${win_port}"
    win_get_fw_rule_cmd="Get-NetFirewallRule | โดยที่ { \$_.DisplayName -eq '${rule_name}' }"
    win_new_fw_rule_cmd="New-NetFirewallRule -DisplayName '${rule_name}' -Direction Inbound -Action Allow -โปรโตคอล TCP -LocalPort ${win_port}"

    ถ้า ! อินเตอร์เฟส netsh.exe portproxy แสดงทั้งหมด | grep -q -P "${win_ip}\s+${win_port}\s+${wsl_ip}\s+${wsl_port}"
    แล้ว
        powershell.exe กระบวนการเริ่มต้น - กริยา runAs - เส้นทางไฟล์ "netsh.exe" \
            -ArgumentList "อินเทอร์เฟซ","portproxy","เพิ่ม","v4tov4",\
                    "listenport=$win_port","listenaddress=$win_ip",\
                    "connectport=$wsl_port","ที่อยู่เชื่อมต่อ=$wsl_ip"

        ถ้า [[ $? -eq 0 ]]
        แล้ว
            echo "สร้างพอร์ตพร็อกซี '${win_ip}:${win_port} > ${wsl_ip}:${wsl_port}' แล้ว"
        อื่น
            echo "พอร์ตพร็อกซี '${win_ip}:${win_port} > ${wsl_ip}:${wsl_port}' ล้มเหลว"
        ไฟ

        ถ้า ! powershell.exe ${win_get_fw_rule_cmd} | grep -q "$rule_name"
        แล้ว
            echo "เปิด PowerShell ในฐานะผู้ดูแลระบบและสร้างกฎไฟร์วอลล์ต่อไปนี้:"
            เสียงสะท้อน -e '\033[1;33m'"$win_new_fw_rule_cmd"'\033[0m'
        ไฟ
    ไฟ
}
wsl_win_proxy

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

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

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


คำสั่งของ PowerShell ต่อไปนี้จะช่วยคุณจัดการคำสั่งที่สร้างขึ้น พร็อกซีพอร์ต.

netsh interface portproxy แสดงทั้งหมด
รีเซ็ต portproxy ของอินเตอร์เฟส netsh

อ้างอิง:

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา