This repository has been archived by the owner on Aug 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
block external traffic when takedown flag is present (#24)
* initial implementation * include lua-resty-ipmatcher in the docker image * refactor the code * refactor the code * fix typo * fix import * fix shared dict usage * dns resolver * change dns resolver * log ip * use server ip env var * drop resolver * fix formatting * block hns * fix duplicate access_by_lua_block * add to generic portal check * refactor imports * block tus and trustless download * unused skynet_utils * drop unnecessary server ip env var requirement * update docker test image * update testing image * revert some changes to test docker image * add lua-resty-ipmatcher to testing setup * create exit_public_access_forbidden * deny registry access too * increase test coverage * refactor exit functions * unused argument message * no trailing whitespace * luacov disable untestable function * rename function and add test coverage * docs typo
- Loading branch information
Showing
13 changed files
with
268 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,19 @@ | ||
access_by_lua_block { | ||
local skynet_access = require("skynet.access") | ||
local skynet_account = require("skynet.account") | ||
|
||
-- check if portal should be blocking public access to api | ||
if skynet_access.should_block_access(ngx.var.remote_addr) then | ||
return skynet_access.exit_public_access_forbidden() | ||
end | ||
|
||
-- check portal access rules and exit if access is restricted | ||
if require("skynet.account").is_access_unauthorized() then | ||
return require("skynet.account").exit_access_unauthorized() | ||
if skynet_account.is_access_unauthorized() then | ||
return skynet_account.exit_access_unauthorized() | ||
end | ||
|
||
-- check if portal is in subscription only mode | ||
if require("skynet.account").is_access_forbidden() then | ||
return require("skynet.account").exit_access_forbidden() | ||
if skynet_account.is_access_forbidden() then | ||
return skynet_account.exit_access_forbidden() | ||
end | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
local _M = {} | ||
|
||
-- imports | ||
local utils = require("utils") | ||
local skynet_utils = require("skynet.utils") | ||
|
||
function _M.match_allowed_internal_networks(ip_addr) | ||
local ipmatcher = require("resty.ipmatcher") | ||
local ipmatcher_private_network = ipmatcher.new({ | ||
"127.0.0.0/8", -- host network | ||
"10.0.0.0/8", -- private network | ||
"172.16.0.0/12", -- private network | ||
"192.168.0.0/16", -- private network | ||
}) | ||
|
||
return ipmatcher_private_network:match(ip_addr) | ||
end | ||
|
||
-- function that decides whether the request should be blocked or not | ||
-- based on portal settings and request properties (ngx.var.remote_addr) | ||
function _M.should_block_access(remote_addr) | ||
-- deny public access has to be explictly set to true to block traffic | ||
if utils.getenv("DENY_PUBLIC_ACCESS", "boolean") ~= true then | ||
return false | ||
end | ||
|
||
-- block access only when the request does not come from allowed internal network | ||
return _M.match_allowed_internal_networks(remote_addr) == false | ||
end | ||
|
||
-- handle request exit when access to portal should deny public access | ||
function _M.exit_public_access_forbidden() | ||
return skynet_utils.exit(ngx.HTTP_FORBIDDEN, "Server public access denied") | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
local utils = require("utils") | ||
local skynet_access = require("skynet.access") | ||
local skynet_utils = require("skynet.utils") | ||
|
||
describe("match_allowed_internal_networks", function() | ||
it("should return true for addresses from 127.0.0.0/8 host network", function() | ||
-- start and end of the range | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.0.0.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.255.255.255")) | ||
-- random addresses from the network | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.0.0.1")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.10.0.100")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.99.210.3")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("127.210.20.99")) | ||
end) | ||
|
||
it("should return true for addresses from 10.0.0.0/8 private network", function() | ||
-- start and end of the range | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.0.0.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.255.255.255")) | ||
-- random addresses from the network | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.10.1.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.10.10.10")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.87.10.120")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("10.210.23.255")) | ||
end) | ||
|
||
it("should return true for addresses from 172.16.0.0/12 private network", function() | ||
-- start and end of the range | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.0.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.255.255")) | ||
-- random addresses from the network | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.1.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.10.10")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.10.120")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("172.16.230.55")) | ||
end) | ||
|
||
it("should return true for addresses from 192.168.0.0/16 private network", function() | ||
-- start and end of the range | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.0.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.255.255")) | ||
-- random addresses from the network | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.1.0")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.10.10")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.10.120")) | ||
assert.is_true(skynet_access.match_allowed_internal_networks("192.168.230.55")) | ||
end) | ||
|
||
it("should return false for addresses from outside of allowed networks", function() | ||
assert.is_false(skynet_access.match_allowed_internal_networks("8.8.8.8")) | ||
assert.is_false(skynet_access.match_allowed_internal_networks("16.12.0.1")) | ||
assert.is_false(skynet_access.match_allowed_internal_networks("115.23.44.17")) | ||
assert.is_false(skynet_access.match_allowed_internal_networks("198.19.0.20")) | ||
assert.is_false(skynet_access.match_allowed_internal_networks("169.254.1.1")) | ||
assert.is_false(skynet_access.match_allowed_internal_networks("212.32.41.12")) | ||
end) | ||
end) | ||
|
||
describe("should_block_access", function() | ||
local remote_addr = "127.0.0.1" | ||
|
||
before_each(function() | ||
stub(utils, "getenv") | ||
stub(skynet_access, "match_allowed_internal_networks") | ||
end) | ||
|
||
after_each(function() | ||
mock.revert(utils) | ||
mock.revert(skynet_access) | ||
end) | ||
|
||
it("should not block access if DENY_PUBLIC_ACCESS is not set", function() | ||
utils.getenv.on_call_with("DENY_PUBLIC_ACCESS").returns(nil) | ||
|
||
assert.is_false(skynet_access.should_block_access(remote_addr)) | ||
end) | ||
|
||
it("should not block access if DENY_PUBLIC_ACCESS is set to false", function() | ||
utils.getenv.on_call_with("DENY_PUBLIC_ACCESS").returns(false) | ||
|
||
assert.is_false(skynet_access.should_block_access(remote_addr)) | ||
end) | ||
|
||
it("should not block access if DENY_PUBLIC_ACCESS is set to true but request is from internal network", function() | ||
utils.getenv.on_call_with("DENY_PUBLIC_ACCESS").returns(true) | ||
skynet_access.match_allowed_internal_networks.on_call_with(remote_addr).returns(true) | ||
|
||
assert.is_false(skynet_access.should_block_access(remote_addr)) | ||
end) | ||
|
||
it("should block access if DENY_PUBLIC_ACCESS is set to true and request is not from internal network", function() | ||
utils.getenv.on_call_with("DENY_PUBLIC_ACCESS", "boolean").returns(true) | ||
skynet_access.match_allowed_internal_networks.on_call_with(remote_addr).returns(false) | ||
|
||
assert.is_true(skynet_access.should_block_access(remote_addr)) | ||
end) | ||
end) | ||
|
||
describe("exit_public_access_forbidden", function() | ||
before_each(function() | ||
stub(skynet_utils, "exit") | ||
end) | ||
|
||
after_each(function() | ||
mock.revert(skynet_utils) | ||
end) | ||
|
||
it("should call exit with status code 403 and proper message", function() | ||
skynet_access.exit_public_access_forbidden() | ||
|
||
assert.stub(skynet_utils.exit).was_called_with(403, "Server public access denied") | ||
end) | ||
end) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.