Restringir una conexión de SQL Server a una dirección IP específica

Quiero restringir las conexiones a mi instancia de SQL Server a direcciones IP específicas. Quiero evitar cualquier conexión desde cualquier dirección IP, excepto una lista específica. ¿Es esto algo que se puede configurar en la instancia o base de datos de SQL Server?

Suena como algo que harías con el firewall de Windows (puedes bloquear los puertos de SQL Server y permitir excepciones para ciertas direcciones IP).

Podrías hacer esto con algo así como un disparador de inicio de sesión que verificara la dirección IP usando sys.dm_exec_connections pero creo que es una opción mucho menos deseable que bloquear el tráfico directamente.

Ciertamente mucho más difícil de hacer a nivel de base de datos.

Escribí esta funcionalidad para prohibir automáticamente una dirección IP que haya realizado más bashs de inicio de sesión de X ( @FailedLoginAttempts ) desde la misma dirección IP. Se basa en los registros de errores de SQL Server. Estoy ejecutando un Windows Server 2008 y SQL Server 2008 R2.

Tenga en cuenta que si no ha completado el ciclo de los registros de errores de SQL Server en un momento, puede obtener una gran cantidad de direcciones IP y puede tomar un poco de tiempo para procesar todo. Cuando ejecuto esto cada 10 minutos, todo el proceso dura de 4 a 5 segundos.

Pasos

  1. Asegúrate de que estás iniciando bashs fallidos. En SQL Server Management Studio (SSMS), haga clic con el botón derecho en su instancia (arriba de sus bases de datos) PropiedadesSeguridadAuditoría de inicio de sesión . Asegúrese de que el botón de opción sea [Solo inicios de sesión fallidos] || [Ambos inicios de sesión fallidos y exitosos] están seleccionados.
  2. Crea la tabla para almacenar direcciones IP prohibidas

    /* Create table to store banned IP addresses */ USE [YourDB] GO CREATE TABLE [dbo].[autobanned_ipaddesses]( [id] [int] IDENTITY(1,1) NOT NULL, [ipaddress] [varchar](50) NOT NULL, [attacked_on] [datetime2](2) NOT NULL, [banned_on] [datetime2](7) NOT NULL, [number_login_attempts] [int] NULL, CONSTRAINT [PK_autobanned_ipaddesses] PRIMARY KEY CLUSTERED ([id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]) ON [PRIMARY] ALTER TABLE [dbo].[autobanned_ipaddesses] ADD CONSTRAINT [DF_autobanned_ipaddesses_banned_on] DEFAULT (getdate()) FOR [banned_on] 
  3. Cree el proceso para agregar automáticamente direcciones IP al firewall. Personalmente coloqué este código en un trabajo de agente que se ejecuta cada 10 minutos. También tenga en cuenta que este proceso utiliza xp_cmdshell . Ciertamente no quiero debatir los méritos de habilitar o deshabilitar esta funcionalidad. Para cada uno, pero mi script no funcionará sin esta funcionalidad. Si no lo tiene habilitado aquí hay un buen enlace para ayudarlo.

     USE [YourDB] DECLARE @T TABLE(LogDate datetime,ProcessInfo varchar(200),Text varchar(max)) DECLARE @T2 TABLE(LogDate datetime,ProcessInfo varchar(200),IPAddress varchar(max)) DECLARE @T3 TABLE(LogDate datetime,IPAddress varchar(max)) DECLARE @IPAddress varchar(50),@LogDate datetime,@NumLoginAttempts int,@CmdExc varchar(300),@FailedLoginAttempts int=10 BEGIN /* Get error log records with failed login attempt data */ INSERT INTO @T EXEC sp_readerrorlog 0,1,'Could not find a login matching the name provided' INSERT INTO @T EXEC sp_readerrorlog 0,1,'An error occurred while evaluating the password' END BEGIN /* Get the IP address from T*/ INSERT INTO @T2 SELECT LogDate,ProcessInfo,REPLACE(REPLACE( SUBSTRING(Text, PATINDEX ('%[0-9].%[0-9].%[0-9].[0-9]%',Text)-2,50),']',''),':','') FROM @T END BEGIN /* Get the NEW ip addresses from T2*/ INSERT INTO @T3 SELECT CONVERT(varchar(10),LogDate,101) LogDate,IPAddress from @T2 T WHERE NOT EXISTS(SELECT * FROM autobanned_ipaddesses ai WHERE ai.ipaddress=T.IPAddress) GROUP BY CONVERT(varchar(10),LogDate,101),IPAddress HAVING COUNT(LogDate)>@FailedLoginAttempts ORDER BY IPAddress END BEGIN /* Validate that T3 has records, if not skip the firewall add */ IF (SELECT COUNT(*) FROM @T3)=0 BEGIN GOTO ExitWithoutCycle END END BEGIN /* Loop through T3 and add each entry to the windows firewall */ WHILE EXISTS(SELECT * FROM @T3) BEGIN SELECT TOP(1) @LogDate=LogDate, @IPAddress=IPAddress FROM @T3 SELECT @NumLoginAttempts=COUNT(*) FROM @T2 WHERE IPAddress=@IPAddress INSERT INTO autobanned_ipaddesses (attacked_on,ipaddress,number_login_attempts) VALUES(@LogDate,@IPAddress,@NumLoginAttempts) SET @CmdExc = 'netsh advfirewall firewall add rule name="Autobanned IP - SQL Attacked '+@IPAddress+'" dir=in action=block enable="yes" remoteip='+@IPAddress+' protocol=any interfacetype=any' EXEC master..xp_cmdshell @CmdExc DELETE @T3 WHERE IPAddress=@IPAddress END END /* sp_cycle_errorlog archives the current error log. */ EXEC sp_cycle_errorlog ExitWithoutCycle: 

Entiendo que esta no es una solución perfecta, ya que solo funciona con direcciones IPv4 y solo analiza los bashs de inicio de sesión realizados probablemente a través del puerto 1433 dependiendo de su configuración. Sin embargo, me ha ayudado a identificar y bloquear más de 100 direcciones IP en una semana más o menos (principalmente en China y Hong Kong, pero bloqueé el Departamento de Seguridad Nacional ).

TANGENT – Una vez que ejecuté esto por una semana más o menos, me di cuenta rápidamente de que había una buena cantidad de patrones en los rangos netos de las direcciones IP. Encontré que esta herramienta era muy útil para determinar quién y de dónde provenían estos éxitos. Lo bueno de este sitio web es que una vez que obtiene la ubicación de la dirección IP, a continuación puede ingresar la dirección IP nuevamente y obtener el rango neto de la dirección IP. Por ejemplo (perdón China), encontré que 59.53.67.13 tenía un rango neto de 59.0.0.0 – 59.255.255.255. Una vez dicho esto, creé una función manual para bloquear todo el rango de red y eliminar cualquier regla de Firewall de Windows que ya contenga direcciones IP en este rango.

  USE [YourDB] DECLARE @CmdExc varchar(300) DECLARE @NetRange varchar(50)='59.0.0.0 - 59.255.255.255' DECLARE @NetRangeFrom varchar(20),@NetRangeTo varchar(20),@IPAddress varchar(20) DECLARE @IPPart2From int,@IPPart2To int DECLARE @IPPartSearch2From int,@IPPartSearch2To int DECLARE @T Table (ipaddress varchar(20)) SET @NetRange=REPLACE(@NetRange,' ','') SELECT @NetRangeFrom=LTRIM(RTRIM(SUBSTRING(@NetRange,1,CHARINDEX('-',@NetRange)-1))) SELECT @NetRangeTO=LTRIM(RTRIM(SUBSTRING(@NetRange,CHARINDEX('-',@NetRange)+1,50))) SELECT @IPPartSearch2From=CAST(PARSENAME(@NetRangeFrom,3) as int) SELECT @IPPartSearch2To=CAST(PARSENAME(@NetRangeTo,3) as int) INSERT INTO @T select ai.ipaddress from autobanned_ipaddesses ai where LTRIM(ai.ipaddress) like SUBSTRING(@NetRangeFrom,1,CHARINDEX('.',@NetRangeFrom,1))+'%' AND PARSENAME(LTRIM(RTRIM(ai.ipaddress)),3) BETWEEN @IPPartSearch2From AND @IPPartSearch2To SET @CmdExc = 'netsh advfirewall firewall add rule name="AB SQL Attacked '+@NetRange+'" dir=in action=block enable="yes" remoteip='+@NetRange EXEC master..xp_cmdshell @CmdExc WHILE EXISTS(SELECT * from @T) BEGIN SELECT TOP(1) @IPAddress=ipaddress from @T SET @CmdExc = 'netsh advfirewall firewall delete rule name="Autobanned IP - SQL Attacked '+@IPAddress+'"' EXEC master..xp_cmdshell @CmdExc DELETE TOP(1) FROM @T END 

Espero comentarios que mejoren esta funcionalidad.

Supongo que podría escribir un activador de inicio de sesión como se describe aquí que comprueba de dónde están ingresando, pero sugeriría que sería mejor usar un firewall.

  1. Use un firewall externo como Baracuda o F5: la mejor opción para reducir la carga en el servidor de Windows.
  2. Configuración de Firewall de Windows: cuando no pueda hacer lo anterior, configure los ajustes del firewall entrante y abra el puerto 1433 y en la pestaña de Computadora remota, ingrese su dirección IP de origen.
  3. En el nivel de red del servidor SQL – Configuración de red del servidor SQL * → AvanzadoSPN NTLM aceptados . Agregue los nombres de dominio aquí.
  4. Siga el procedimiento de Matt Smith con el disparador