I want to restrict the connections to my SQL Server instance to specific IP addresses. I want to prevent any connections from any IP addresses except a specific list. Is this something that can be configured in the SQL Server instance or database?

- 30,738
- 21
- 105
- 131

- 2,926
- 3
- 23
- 30
-
3this sounds like a perfectly valid thing to do.. Im embarrassed that SQL Server doesn't have this functionality (when mySQL does have this capability) – Aaron Kempf Dec 15 '12 at 21:47
5 Answers
Sounds like something you'd do using the Windows firewall (you can block the SQL Server port(s), and allow exceptions for certain IP addresses).
You could do this with something like a logon trigger that checked the IP address using sys.dm_exec_connections but I think it's a much less desirable option than blocking the traffic outright.
Certainly much tougher to do at the database level.

- 272,866
- 37
- 466
- 490
-
10+1 for thinking outside of SQL Server... Use the right tool for the job :) – Oded Aug 19 '11 at 21:32
-
1Thanks for this answer. Yes, it make sense to do this in the firewall but I thought that this would be provided in SQL Server as an upper layer of security. – mohammedn Aug 19 '11 at 22:12
-
Not really - there are many ways you can connect to SQL Server - shared memory, named pipes, TCP/IP - and with IP addresses these can change (e.g. at ISP level, or with DHCP using ipconfig /renew) or you can be on different subnets, on a VPN, etc. Obviously blocking an IP address isn't going to help in all of those cases. – Aaron Bertrand Aug 19 '11 at 22:42
-
2As another comment, note that SQL Server is pretty secure by default these days. You have to go out of your way to let traffic in. Just take a look at how often the "SQL Server does not allow remote connections" error has surfaced on SO/SF due to the more secure default settings: http://is.gd/zAuLcV / http://is.gd/7PZOIC ... sorry about the shortened links, but they're really long (might not even fit into a comment in whole). – Aaron Bertrand Aug 19 '11 at 22:54
-
Could someone confirm whether Windows firewall can actually do so? I'm probably missing something but I can only add exceptions for items in the local Windows network (computers, users, etc.), not arbitrary IP address from the internet. – Álvaro González Jul 08 '16 at 12:24
-
@ÁlvaroGonzález Might be slightly different depending on operating system, but see http://superuser.com/questions/231358/allowing-ip-range-in-windows-firewall and https://technet.microsoft.com/en-us/library/cc753558(v=ws.11).aspx – Aaron Bertrand Jul 08 '16 at 18:48
-
@AaronBertrand Thank you. I feel dumb: I was looking for it in the *New Rule* wizard but it isn't there in Windows Server 2012, you need to create a rule first and then edit it. – Álvaro González Jul 11 '16 at 10:58
I wrote this functionality to auto ban an IP address that has made more than X (@FailedLoginAttempts) log in attempts from the same IP address. It is based on the SQL Server Error Logs. I am running a Windows Server 2008 and SQL Server 2008 R2.
Be advised if you have not cycled your SQL Server Error Logs in a while, you may get a great many IP addresses and it may take a little time to process everything. As I run this every 10 minutes the whole process takes about 4-5 seconds.
Steps
- Insure you are logging failed attempts. In SQL Server Management Studio (SSMS) right click your instance (above your databases) Properties → Security → Login auditing. Make sure the radio button for either [Failed logins only] || [Both failed and successful logins] is selected.
Create the table to store banned IP addresses
/* 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]
Create the process to auto add IP addresses to the firewall. Personally I placed this code in an Agent Job running every 10 minutes. Also note that this process utilizes xp_cmdshell. I certainly don't want to debate the merits of enabling or disabling this functionality. To each their own, but my script won't work without this functionality. If you don't have it enabled here is a good link to help you.
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:
I understand that this is not a perfect solution, because it only works with IPv4 IP addresses and only looks at log in attempts made through probably port 1433 depending on your configuration. However it has helped me identify and block over 100 IP addresses in a week or so (mainly China and Hong Kong, but I did block the Department of Homeland Security).
TANGENT - Once I ran this for a week or so I quickly realized there were a fair amount of patterns in the net ranges of the IP addresses. I found this tool to be most helpful to nail down who and where these hits were coming from. The thing that is great about this website is that once you get the location of the IP address, down below you can input the IP address again and get the net range of the IP address. For instance (sorry China), I found that 59.53.67.13 had a net range of 59.0.0.0 - 59.255.255.255. That being said, I created a manual function to block the entire net range and delete any Windows Firewall rules that already contained IP addresses in this range.
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
I am looking forward to comments that improve this functionality.

- 30,738
- 21
- 105
- 131

- 2,385
- 2
- 15
- 14
-
1Very interesting approach! Unfortunately I am getting 'The requested operation requires elevation (Run as administrator).' when trying to add the firewall rule. I am still trying to find a way of running this... – HansLindgren May 05 '16 at 14:04
-
(A bit similar problem to http://stackoverflow.com/questions/19192210/re-enable-remote-desktop-windows-firewall-rule-on-windows-azure) – HansLindgren May 05 '16 at 14:12
-
@matt smith I'm having force brute attacks to my sql server, so I will give a try to you sp, it is exactly was I looking for. Thx u very much. – Artemination Sep 02 '16 at 18:42
-
@HansLindgren I'm having the same problem 'The requested operation requires elevation (Run as administrator).' but when i create a sql server agent job then I found that "Run as user" option available in "T-SQL Step". When you specified Administrator in "Run as user" then no error occur. – Husain Sanwerwala Nov 03 '16 at 12:54
-
"Personally I placed this code in an Agent Job running every 10 minutes." How do you do this? – Yoni Jul 04 '23 at 15:00
- Use an external firewall like Baracuda or F5 - Best option so that you reduce the load on the Windows server.
- Windows Firewall Settings - When you can't do the above, set the incoming firewall settings and open port 1433 and in the Remote Computer tab enter your source IP address.
- At the SQL Server Networking Level - SQL Server Network Configuration* → Advanced → Accepted NTLM SPNs. Add the domain names here.
- Follow Matt Smith's procedure with trigger

- 30,738
- 21
- 105
- 131

- 450
- 3
- 8
I suppose you could write a logon trigger as described here that checks where they're logging in from, but I'd suggest that it would be better to use a firewall.

- 54,199
- 15
- 94
- 116
-
1Note that this doesn't prevent the connection per se, it just prevents a successful logon. – Aaron Bertrand Aug 10 '12 at 14:19
I would have to agree whole heartedly with Peter Mortensens answer. If you want this to scale well, first try to get dedicated hardware. If not, then windows firewall. Your server should only be concerning itself with its task which is being a database. Its like development, have a single responsibility/reason for an item.

- 19
- 4