วิธีระบุที่อยู่ IP ของเซิร์ฟเวอร์ใน PHP


122

ฉันจะระบุที่อยู่ IP ของเซิร์ฟเวอร์ใน PHP ได้อย่างไร


2
คุณหมายถึงที่อยู่ IP ของคำขอหรือ IP ของเครื่องที่เรียกใช้แอปของคุณหรือไม่?
wosis

คำตอบ:


175

เช่นนี้สำหรับเซิร์ฟเวอร์ ip:

$_SERVER['SERVER_ADDR'];

และสิ่งนี้สำหรับพอร์ต

$_SERVER['SERVER_PORT'];

10
ไม่สำหรับโฮสต์ที่ใช้ร่วมกันบางโฮสต์ผลตอบแทน :: 1
TheRealChx101

3
สิ่งนี้อาจไม่ถูกต้องขึ้นอยู่กับ Load Balancer ที่ใช้หน้าเว็บเซิร์ฟเวอร์ของคุณ คุณต้องการส่วนหัว X-Forwarded-For เช่นกันในสถานการณ์นี้: en.wikipedia.org/wiki/X-Forwarded-For
Ligemer

31
นี่ไม่ใช่ที่อยู่เซิร์ฟเวอร์! นี่คือที่อยู่ที่เบราว์เซอร์ระยะไกลเรียกเซิร์ฟเวอร์ซึ่งอยู่ภายใต้การควบคุมของผู้ใช้ระยะไกล ใช้คำJohn Kตอบแทน
Ariel

สิ่งนี้ไม่ได้ให้ ip ของเซิร์ฟเวอร์ ด้วยเหตุผลบางอย่างมันคือการให้ ip ในพื้นที่ของฉัน
Thomas Williams

นอกจากนี้ยังไม่ให้ที่อยู่เซิร์ฟเวอร์ php-fpm แต่สำหรับเว็บเซิร์ฟเวอร์ที่เกี่ยวข้อง (nginx, apache) ดังนั้นจึงไม่ถูกต้องสำหรับข้อกำหนดโฮสต์ mysql-client (user @ host)
scipilot

105

หากคุณใช้ PHP เวอร์ชัน 5.3 ขึ้นไปคุณสามารถทำสิ่งต่อไปนี้:

$host= gethostname();
$ip = gethostbyname($host);

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


สมบูรณ์แบบสิ่งที่ฉันกำลังมองหา ขอบคุณ John
Frank

6
+1 นี่เป็นทางออกเดียวที่จะใช้ได้กับบรรทัดคำสั่ง
Adam Elsodaney

2
@andreas มันไม่ควร. ชื่อโฮสต์ท้องถิ่นควรจะอยู่ใน/etc/hostsไฟล์และจะได้อย่างรวดเร็ว - 127.0.0.1แม้ว่ามันก็อาจจะ ถ้ามันต้องเรียก DNS ก็จะช้าเหมือนที่คุณพูด
Ariel

+1 แต่แค่คำถาม .. ฉันลองใช้ xampp บนเซิร์ฟเวอร์ท้องถิ่นและส่งคืน ip 192.168etc แต่ .. ควรเป็น 127.0.0.1 ไม่ใช่ ??
Andrea Bori

สิ่งนี้ใช้ได้กับฉัน แต่บางเครื่องแสดงชื่อโดเมน วิธีแก้ไขปัญหานี้
Dharani Dharan

19

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

$_SERVER['SERVER_ADDR']

เมื่อคุณใช้ IIS ให้ลอง:

$_SERVER['LOCAL_ADDR']

2
$_SERVER['LOCAL_ADDR']ใช้ได้เฉพาะภายใต้ IIS เมื่อ PHP ทำงานเป็นโมดูล CGI
Rudi Visser

@rudi_visser มันใช้งานได้กับ fastcgi เช่นกัน แต่ถ้าคุณเชื่อมต่อผ่าน locahost คุณจะได้รับ :: 1 กลับมาแทน หากคุณเชื่อมต่อผ่านชื่อเซิร์ฟเวอร์หรือ ip คุณจะได้รับ ip จริงกลับคืนมา
starbeamrainbowlabs

@starbeamrainbowlabs FastCGI คือ CGI :) ฉันหมายถึงในทางตรงกันข้ามกับการทำงานเป็นโมดูล ISAPI ซึ่งเขียนขึ้นก่อนการถือกำเนิดครั้งสำคัญของ FastCGI ในฐานะแพลตฟอร์มที่มีเสถียรภาพ
Rudi Visser

@starbeamrainbowlabs อะไรก็ได้ที่ดูเหมือน :: 1 น่าจะเป็นที่อยู่ IP6
Toby Allen

@TobyAllen ขอบคุณค่ะ :). สิ่งที่แปลกคือเครือข่ายของฉันไม่รองรับ ipv6 แต่เซิร์ฟเวอร์ของฉัน (เครื่อง windows 7) รายงาน IP เป็น :: 1 ที่อยู่ลูปแบ็ค ipv6
starbeamrainbowlabs

13

ฉันมาที่หน้านี้เพื่อค้นหาวิธีรับที่อยู่ IP ของตัวเองไม่ใช่ของเครื่องระยะไกลที่เชื่อมต่อกับฉัน

สิ่งนี้จะใช้ไม่ได้กับเครื่อง windows

แต่ในกรณีที่มีคนค้นหาสิ่งที่ฉันกำลังมองหา:

#! /usr/bin/php
<?php
$my_current_ip=exec("ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'");
echo $my_current_ip;

(ดัดแปลงอย่างไร้ยางอายจากฉันจะรับที่อยู่ IP หลักของเครื่องโลคัลบน Linux และ OS X ได้อย่างไร )


นี่เป็นตัวเลือกเดียวที่ใช้งานได้จริงเมื่อเรียกใช้สคริปต์ PHP จากเชลล์ คำถาม: เมื่อมีอินเทอร์เฟซที่ใช้งานอยู่หลายรายการสิ่งนี้จะตัดสินใจได้อย่างไรว่าจะส่งคืนที่อยู่ใด ฉันทดสอบด้วยการเชื่อมต่ออีเธอร์เน็ตแบบมีสายและไร้สายที่เปิดใช้งานอยู่และจากนั้นใช้งานแบบไร้สายเท่านั้นและจะส่งคืน wlan ip ทั้งสองครั้ง สคริปต์ที่ดีขอบคุณ!
Ryan Griggs

ไม่ทราบจริงว่าจะกลับตัวไหน เพียงส่งคืนอินเทอร์เฟซ inet สุดท้ายจากเอาต์พุตของ ifconfig แต่ละเว้น 127.0.0.1 หากคุณมีเพียงอินเทอร์เฟซ "ปกติ" แสดงว่ามันทำงานได้ดีทีเดียว น่าจะปลอดภัยที่สุดหากคุณระบุอินเทอร์เฟซที่คุณต้องการ "ifconfig wlan0 | ... " สคริปต์นี้ไม่ได้สมบูรณ์แบบ แต่ใช้งานได้ในการตั้งค่าที่เรียบง่ายและแสดงให้เห็นถึงวิธีการดำเนินการตามหลักการเพื่อให้ปรับเปลี่ยนได้ตามต้องการ
Dom

1
ifconfig | grep 'inet addr' | ตัด -d ':' -f 2 | awk '{print $ 1}' | grep -vE '^ (192 \ .168 | 10 \. | 172 \ .1 [6789] \. | 172 \ .2 [0-9] \. | 172 \ .3 [01] \. | 127 \. ) 'เป็นการแก้ไขล่าสุดของฉันในเรื่องนี้ มันกรอง ips ในเครื่องทั้งหมดออกและให้เฉพาะภายนอกเท่านั้น
Dom

ฉันมีอินเทอร์เฟซเครือข่ายหลายตัวฉันจึงทำifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | grep -e '192\.168\.1\.'
โจนาธาน

10

คำตอบที่ได้รับการโหวตมากที่สุดจะไม่ส่งคืนที่อยู่สาธารณะของเซิร์ฟเวอร์อย่างน่าเชื่อถือ โดยทั่วไป$_SERVER['SERVER_ADDR']จะถูกต้อง แต่หากคุณกำลังเข้าถึงเซิร์ฟเวอร์ผ่าน VPN ก็มีแนวโน้มที่จะส่งคืนที่อยู่เครือข่ายภายในแทนที่จะเป็นที่อยู่สาธารณะและแม้ว่าจะไม่ได้อยู่ในเครือข่ายเดียวกันก็ตามการกำหนดค่าบางอย่างก็จะว่างเปล่าหรือมีการระบุอื่น ๆ ความคุ้มค่า

ในทำนองเดียวกันมีบางสถานการณ์ที่$host= gethostname(); $ip = gethostbyname($host);จะไม่ส่งคืนค่าที่ถูกต้องเนื่องจากอาศัยทั้ง DNS (ทั้งที่กำหนดค่าภายในหรือบันทึกภายนอก) และการตั้งค่าชื่อโฮสต์ของเซิร์ฟเวอร์เพื่อคาดการณ์ที่อยู่ IP ของเซิร์ฟเวอร์ ขั้นตอนทั้งสองนี้อาจผิดพลาดได้ ตัวอย่างเช่นหากชื่อโฮสต์ของเซิร์ฟเวอร์มีรูปแบบเหมือนชื่อโดเมน (เช่นHOSTNAME=yahoo.com) จากนั้น (อย่างน้อยในการตั้งค่า php5.4 / Centos6 ของฉัน) gethostbynameจะข้ามไปที่การค้นหาที่อยู่ของ Yahoo.com โดยตรงแทนที่จะเป็นของเซิร์ฟเวอร์ภายใน

นอกจากนี้เนื่องจากการgethostbynameกลับไปใช้ DNS สาธารณะจะบันทึกเซิร์ฟเวอร์ทดสอบที่มีระเบียน DNS สาธารณะที่ไม่ได้เผยแพร่หรือไม่ถูกต้อง (ตัวอย่างเช่นคุณกำลังเข้าถึงเซิร์ฟเวอร์โดยlocalhostหรือที่อยู่ IP หรือหากคุณกำลังแทนที่ DNS สาธารณะโดยใช้hostsไฟล์ในเครื่องของคุณ) คุณก็จะ ' จะได้รับคืนทั้งที่ไม่มีที่อยู่ IP (มันจะส่งคืนชื่อโฮสต์) หรือที่แย่กว่านั้นคือจะส่งคืนที่อยู่ที่ไม่ถูกต้องที่ระบุในระเบียน DNS สาธารณะหากมีอยู่หรือมีสัญลักษณ์แทนสำหรับโดเมน

คุณสามารถลองแนวทางที่สามโดยทำสิ่งนี้ขึ้นอยู่กับสถานการณ์:

$external_ip = exec('curl http://ipecho.net/plain; echo');

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


10

นี่คือสิ่งที่คุณสามารถใช้เป็นการปรับตัวอย่างข้างต้นได้โดยไม่ต้องกังวลเกี่ยวกับ curl ที่ติดตั้งบนเซิร์ฟเวอร์ของคุณ

<?php
      // create a new cURL resource
      $ch = curl_init ();

      // set URL and other appropriate options
      curl_setopt ($ch, CURLOPT_URL, "http://ipecho.net/plain");
      curl_setopt ($ch, CURLOPT_HEADER, 0);
      curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);

      // grab URL and pass it to the browser

      $ip = curl_exec ($ch);
      echo "The public ip for this server is: $ip";
      // close cURL resource, and free up system resources
      curl_close ($ch);
    ?>


5

หากคุณใช้ PHP ใน bash shell คุณสามารถใช้:

$server_name=exec('hostname');

เพราะ$_SERVER[] SERVER_ADDR, HTTP_HOSTและSERVER_NAMEไม่ได้ตั้งค่า


4

คำตอบก่อนหน้านี้ให้ $ _SERVER ['SERVER_ADDR'] สิ่งนี้จะใช้ไม่ได้กับการติดตั้ง IIS บางอย่าง หากคุณต้องการให้สิ่งนี้ทำงานบน IIS ให้ใช้สิ่งต่อไปนี้:

$server_ip = gethostbyname($_SERVER['SERVER_NAME']);

2

ฉันพบว่าสิ่งนี้ใช้ได้กับฉัน: GetHostByName ("");

เรียกใช้ XAMPP v1.7.1 บน Windows 7 ที่ใช้เว็บเซิร์ฟเวอร์ Apache น่าเสียดายที่ให้ที่อยู่ IP เกตเวย์ของฉัน


2

ฉันเพิ่งสร้างสคริปต์ง่ายๆที่จะนำ $ _SERVER ['REMOTE_ADDR'] และ $ _SERVER ['SERVER_ADDR'] กลับมาใน IIS ดังนั้นคุณจึงไม่ต้องเปลี่ยนทุกตัวแปร เพียงวางข้อความนี้ในไฟล์ php ของคุณที่มีอยู่ในทุกหน้า

/** IIS IP Check **/
if(!$_SERVER['SERVER_ADDR']){ $_SERVER['SERVER_ADDR'] = $_SERVER['LOCAL_ADDR']; }
if(!$_SERVER['REMOTE_ADDR']){ $_SERVER['REMOTE_ADDR'] = $_SERVER['LOCAL_ADDR']; }


1

คุณอาจต้องใช้$HTTP_SERVER_VARS['server_ADDR']หากคุณไม่ได้รับอะไรเลยจากคำตอบด้านบนและหากคุณใช้ PHP เวอร์ชันเก่ากว่า


0

ตรวจสอบอาร์เรย์ $ _SERVER

echo $_SERVER['SERVER_ADDR'];

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

2
คิดไม่ออกว่าคำตอบนี้ไม่เข้ากับคำถามได้อย่างไร คำถามคือ "ฉันจะระบุที่อยู่ IP ของเซิร์ฟเวอร์ใน PHP ได้อย่างไร" OP ควรเรียนรู้วิธีการถามให้ดีขึ้นหรือคุณควรเรียนรู้วิธีอ่านคำถาม นอกจากนี้หากไคลเอนต์อยู่หลังพร็อกซีคุณยังคงเมาไม่ว่าคุณจะพยายามทำอะไรจากฝั่งเซิร์ฟเวอร์ก็ตาม สถานการณ์ที่แตกต่างกันโดยสิ้นเชิงคือเมื่อเซิร์ฟเวอร์อยู่หลังพร็อกซีเนื่องจากคุณสามารถตรวจสอบด้วยส่วนหัว X-FORWARDED-FOR
Luis Masuelli

@deceze $_SERVER["SERVER_ADDR"]ไม่มีส่วนเกี่ยวข้องกับส่วนหัว HTTP สิ่งนี้เต็มไปด้วยซอฟต์แวร์เซิร์ฟเวอร์สิ่งที่เกี่ยวข้องกับ HTTP ทั้งหมดใน $ _SERVER ขึ้นต้นด้วย HTTP_ php.net/manual/en/reserved.variables.server.php
poncha

@poncha ความคิดเห็นของฉันเกี่ยวข้องกับการแก้ไขต้นฉบับของโพสต์นี้
หลอกลวง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.