SQL - ค้นหาเพื่อรับที่อยู่ IP ของเซิร์ฟเวอร์


97

มีแบบสอบถามใน SQL Server 2005 ที่ฉันสามารถใช้เพื่อรับ IP หรือชื่อของเซิร์ฟเวอร์ได้หรือไม่


เมื่อเชื่อมต่อกับ SQL โดยใช้ตัวฟัง AG ปรากฏว่า CONNECTIONPROPERTY ('local_net_address') ส่งคืน IP ของผู้ฟังแทน IP ของเซิร์ฟเวอร์
brian beuning

คำตอบ:


148
SELECT  
   CONNECTIONPROPERTY('net_transport') AS net_transport,
   CONNECTIONPROPERTY('protocol_type') AS protocol_type,
   CONNECTIONPROPERTY('auth_scheme') AS auth_scheme,
   CONNECTIONPROPERTY('local_net_address') AS local_net_address,
   CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
   CONNECTIONPROPERTY('client_net_address') AS client_net_address 

รหัสที่นี่จะให้ที่อยู่ IP แก่คุณ

สิ่งนี้จะใช้ได้กับการร้องขอไคลเอ็นต์ระยะไกลไปยัง SQL 2008 และใหม่กว่า

หากคุณอนุญาตการเชื่อมต่อหน่วยความจำที่ใช้ร่วมกันการทำงานด้านบนบนเซิร์ฟเวอร์จะให้คุณ

  • "หน่วยความจำที่ใช้ร่วมกัน" เป็นค่าสำหรับ "net_transport" และ
  • NULL สำหรับ 'local_net_address' และ
  • ' <local machine>' จะแสดงใน 'client_net_address'

'client_net_address' คือที่อยู่ของคอมพิวเตอร์ที่มีการร้องขอในขณะที่ 'local_net_address' จะเป็นเซิร์ฟเวอร์ SQL (ดังนั้นจึงเป็น NULL บนการเชื่อมต่อหน่วยความจำที่ใช้ร่วมกัน) และที่อยู่ที่คุณจะให้กับบุคคลอื่นหากพวกเขาไม่สามารถใช้ NetBios ของเซิร์ฟเวอร์ได้ ชื่อหรือ FQDN ด้วยเหตุผลบางประการ

ฉันไม่แนะนำอย่างยิ่งที่จะใช้คำตอบนี้ การเปิดใช้งานเชลล์เอาต์เป็นความคิดที่แย่มากใน SQL Server ที่ใช้งานจริง


3
คำตอบที่ดียกเว้นว่าฉันได้รับหมายเลขพอร์ตติดลบ (-15736) สำหรับพอร์ตที่ควรเป็น 49800 ดังนั้นหากค่าลบเพียงแค่เพิ่ม 65536 จะปลอดภัยหรือไม่?
crokusek

หากมีคนต้องการล็อกอินเข้าสู่เซิร์ฟเวอร์ SQL ของคอมพิวเตอร์จากระยะไกลฉันจะให้ IP ใดแก่เขา local_net_address หรือ client_net_address?
david blaine

@rene - กำลังพิจารณา แต่คำตอบเดิมนั้นถูกต้อง (สำหรับ SQL2008 + และการเชื่อมต่อระยะไกล) จึงคิดที่จะชี้แจงว่าพารามิเตอร์ ConnectionProperty หมายถึงอะไร แน่นอนว่าคำตอบของ Chris Leonard (dm_exec_connections) ก็ถูกต้องเช่นกันด้วยเหตุผลเดียวกัน หากคุณคิดว่าภาคผนวกของฉันดีกว่าเป็นคำตอบแยกต่างหากอย่าลังเลที่จะทำเช่นนั้น :) ยังไม่ได้ตอบคำถามมาระยะหนึ่งแล้วดังนั้นนโยบายและกฎที่นี่อาจมีการเปลี่ยนแปลง (จะไปอ่านตอนนี้ ... )
Martin S. Stoller

เหตุผลในการเพิ่มเติมตาม " stackoverflow.com/help/editing ": เพื่อชี้แจงความหมายของโพสต์ (โดยไม่เปลี่ยนความหมายนั้น)
Martin S. Stoller

1
@ MartinS.Stoller ฉันแก้ไขการเพิ่มของคุณเพื่อให้อ่านง่าย โปรดตรวจสอบว่าฉันไม่พลาดอะไร
rene

33

คุณสามารถรับ [hostname] \ [instancename] ได้โดย:

SELECT @@SERVERNAME;

หากต้องการรับเฉพาะชื่อโฮสต์เมื่อคุณมีรูปแบบชื่อโฮสต์ \ อินสแตนซ์:

SELECT LEFT(ltrim(rtrim(@@ServerName)), Charindex('\', ltrim(rtrim(@@ServerName))) -1)

หรืออีกทางหนึ่งตามที่ @GilM ชี้ให้เห็น:

SELECT SERVERPROPERTY('MachineName')

คุณสามารถรับที่อยู่ IP จริงได้โดยใช้สิ่งนี้:

create Procedure sp_get_ip_address (@ip varchar(40) out)
as
begin
Declare @ipLine varchar(200)
Declare @pos int
set nocount on
          set @ip = NULL
          Create table #temp (ipLine varchar(200))
          Insert #temp exec master..xp_cmdshell 'ipconfig'
          select @ipLine = ipLine
          from #temp
          where upper (ipLine) like '%IP ADDRESS%'
          if (isnull (@ipLine,'***') != '***')
          begin 
                set @pos = CharIndex (':',@ipLine,1);
                set @ip = rtrim(ltrim(substring (@ipLine , 
               @pos + 1 ,
                len (@ipLine) - @pos)))
           end 
drop table #temp
set nocount off
end 
go

declare @ip varchar(40)
exec sp_get_ip_address @ip out
print @ip

แหล่งที่มาของสคริปต์ของ SQL


21

เซิร์ฟเวอร์อาจมีที่อยู่ IP หลายรายการที่กำลังรับฟัง หากการเชื่อมต่อของคุณได้รับอนุญาตเซิร์ฟเวอร์ VIEW SERVER STATE คุณสามารถรันแบบสอบถามนี้เพื่อรับที่อยู่ที่คุณเชื่อมต่อกับ SQL Server:

SELECT dec.local_net_address
FROM sys.dm_exec_connections AS dec
WHERE dec.session_id = @@SPID;

โซลูชันนี้ไม่ต้องการให้คุณใช้ระบบปฏิบัติการผ่าน xp_cmdshell ซึ่งเป็นเทคนิคที่ควรปิดใช้งาน (หรืออย่างน้อยก็ปลอดภัยอย่างเคร่งครัด) บนเซิร์ฟเวอร์ที่ใช้งานจริง คุณอาจต้องให้สิทธิ์ VIEW SERVER STATE ในการเข้าสู่ระบบที่เหมาะสม แต่นั่นเป็นความเสี่ยงด้านความปลอดภัยที่น้อยกว่าการเรียกใช้ xp_cmdshell

เทคนิคที่ GilM กล่าวถึงสำหรับชื่อเซิร์ฟเวอร์เป็นเทคนิคที่ต้องการ:

SELECT SERVERPROPERTY(N'MachineName');

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

11

วิธีแก้ปัญหาส่วนใหญ่ในการรับ IP address ผ่าน t-sql จะอยู่ในสองค่ายนี้:

  1. เรียกใช้ipconfig.exeผ่านxp_cmdshellและแยกเอาท์พุท

  2. สอบถาม DMV sys.dm_exec_connections

ฉันไม่ใช่แฟนตัวเลือก # 1 การเปิดใช้งาน xp_cmdshell มีข้อบกพร่องด้านความปลอดภัยและยังมีการแยกวิเคราะห์จำนวนมากที่เกี่ยวข้อง ที่ยุ่งยาก ตัวเลือก # 2 มีความสง่างาม และเป็นโซลูชัน t-sql ที่บริสุทธิ์ซึ่งฉันมักจะชอบ นี่คือแบบสอบถามสองตัวอย่างสำหรับตัวเลือก # 2:

SELECT c.local_net_address
FROM sys.dm_exec_connections AS c
WHERE c.session_id = @@SPID;

SELECT TOP(1) c.local_net_address
FROM sys.dm_exec_connections AS c
WHERE c.local_net_address IS NOT NULL;

บางครั้งคำค้นหาข้างต้นไม่ได้ผล Query # 1 จะคืนค่า NULL หากคุณเชื่อมต่อผ่านหน่วยความจำที่ใช้ร่วมกัน (ล็อกอินและรัน SSMS บนโฮสต์ SQL) แบบสอบถาม # 2 อาจไม่ส่งคืนอะไรเลยหากไม่มีการเชื่อมต่อโดยใช้โปรโตคอลหน่วยความจำที่ไม่ใช้ร่วมกัน สถานการณ์นี้น่าจะเกิดขึ้นเมื่อเชื่อมต่อกับอินสแตนซ์ SQL ที่ติดตั้งใหม่ การแก้ไขปัญหา? บังคับให้เชื่อมต่อผ่าน TCP / IP ในการดำเนินการนี้ให้สร้างการเชื่อมต่อใหม่ใน SSMS และใช้คำนำหน้า "tcp:" กับชื่อเซิร์ฟเวอร์ จากนั้นเรียกใช้แบบสอบถามอีกครั้งและคุณจะได้รับที่อยู่ IP

SSMS - เชื่อมต่อกับ Database Engine


นี่จะให้ ipv4 .. เรารับ ipv6 ได้ไหม?
Shikhil Bhalla


8

- ลองใช้สคริปต์นี้ตามความต้องการของฉัน ฟอร์แมตใหม่เพื่ออ่าน

SELECT  
SERVERPROPERTY('ComputerNamePhysicalNetBios')  as 'Is_Current_Owner'
    ,SERVERPROPERTY('MachineName')  as 'MachineName'
    ,case when @@ServiceName = 
    Right (@@Servername,len(@@ServiceName)) then @@Servername 
      else @@servername +' \ ' + @@Servicename
      end as '@@Servername \ Servicename',  
    CONNECTIONPROPERTY('net_transport') AS net_transport,
    CONNECTIONPROPERTY('local_tcp_port') AS local_tcp_port,
    dec.local_tcp_port,
    CONNECTIONPROPERTY('local_net_address') AS local_net_address,
    dec.local_net_address as 'dec.local_net_address'
    FROM sys.dm_exec_connections AS dec
    WHERE dec.session_id = @@SPID;

ขอบคุณ. เพิ่งต้องอัปเดต dec.local_tcp_port เป็น 'dec.local_tcp_port' เพื่อใช้ในฟังก์ชัน มิฉะนั้นจะบ่นว่ามีสองคอลัมน์ชื่อ local_tcp_port
Steven Van Dorpe

7

คุณสามารถใช้แบบสอบถามบรรทัดคำสั่งและดำเนินการใน mssql:

exec xp_cmdshell 'ipconfig'

2
ซึ่งจะใช้ได้เฉพาะเมื่อxp_cmdshellเปิดใช้งานในการกำหนดค่าความปลอดภัยของเซิร์ฟเวอร์
Javasick


2

วิธีที่ง่ายกว่าในการรับชื่อเครื่องโดยไม่มี \ InstanceName คือ:

SELECT SERVERPROPERTY('MachineName')

1

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่บางทีโซลูชันนี้อาจมีประโยชน์เมื่อคุณต้องการดึงที่อยู่ IP และพอร์ต TCP จากการเชื่อมต่อหน่วยความจำที่ใช้ร่วมกัน (เช่นจากสคริปต์ที่ทำงานใน SSMS ภายในเซิร์ฟเวอร์) กุญแจสำคัญคือการเปิดการเชื่อมต่อรองกับ SQL Server ของคุณโดยใช้ OPENROWSET ซึ่งคุณระบุ 'tcp:' ในสตริงการเชื่อมต่อของคุณ ส่วนที่เหลือของโค้ดเป็นเพียงการสร้างไดนามิก SQL เพื่อหลีกเลี่ยงข้อ จำกัด ของ OPENROWSET ที่ไม่สามารถรับตัวแปรเป็นพารามิเตอร์ได้

DECLARE @ip_address       varchar(15)
DECLARE @tcp_port         int 
DECLARE @connectionstring nvarchar(max) 
DECLARE @parm_definition  nvarchar(max)
DECLARE @command          nvarchar(max)

SET @connectionstring = N'Server=tcp:' + @@SERVERNAME + ';Trusted_Connection=yes;'
SET @parm_definition  = N'@ip_address_OUT varchar(15) OUTPUT
                        , @tcp_port_OUT   int         OUTPUT';

SET @command          = N'SELECT  @ip_address_OUT = a.local_net_address,
                                  @tcp_port_OUT   = a.local_tcp_port
                          FROM OPENROWSET(''SQLNCLI''
                                 , ''' + @connectionstring + '''
                                 , ''SELECT local_net_address
                                          , local_tcp_port
                                     FROM sys.dm_exec_connections
                                     WHERE session_id = @@spid
                                   '') as a'

EXEC SP_executeSQL @command
                 , @parm_definition
                 , @ip_address_OUT = @ip_address OUTPUT
                 , @tcp_port_OUT   = @tcp_port OUTPUT;


SELECT @ip_address, @tcp_port

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