Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions apisix/balancer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ local set_more_tries = balancer.set_more_tries
local get_last_failure = balancer.get_last_failure
local set_timeouts = balancer.set_timeouts
local ngx_now = ngx.now
local str_byte = string.byte

local module_name = "balancer"
local pickers = {}
Expand Down Expand Up @@ -195,12 +194,6 @@ end
local function pick_server(route, ctx)
local up_conf = ctx.upstream_conf

for _, node in ipairs(up_conf.nodes) do
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
node.host = '[' .. node.host .. ']'
end
end

local nodes_count = #up_conf.nodes
if nodes_count == 1 then
local node = up_conf.nodes[1]
Expand Down
17 changes: 15 additions & 2 deletions apisix/upstream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ local tostring = tostring
local ipairs = ipairs
local pairs = pairs
local pcall = pcall
local str_byte = string.byte
local ngx_var = ngx.var
local is_http = ngx.config.subsystem == "http"
local upstreams
Expand Down Expand Up @@ -325,10 +326,16 @@ function _M.upstreams()
end


function _M.check_schema(conf)
local function check_schema(conf)
for _, node in ipairs(conf.nodes or {}) do
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
return false, "IPv6 address must be enclosed with '[' and ']'"
end
end
return core.schema.check(core.schema.upstream, conf)
end

_M.check_schema = check_schema

local function get_chash_key_schema(hash_on)
if not hash_on then
Expand Down Expand Up @@ -357,7 +364,7 @@ end

local function check_upstream_conf(in_dp, conf)
if not in_dp then
local ok, err = core.schema.check(core.schema.upstream, conf)
local ok, err = check_schema(conf)
if not ok then
return false, "invalid configuration: " .. err
end
Expand Down Expand Up @@ -396,6 +403,12 @@ local function check_upstream_conf(in_dp, conf)
.. "wrong ssl type"
end
end
else
for i, node in ipairs(conf.nodes or {}) do
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
conf.nodes[i].host = "[" .. node.host .. "]"
end
end
end

if is_http then
Expand Down
30 changes: 30 additions & 0 deletions t/admin/upstream.t
Original file line number Diff line number Diff line change
Expand Up @@ -722,3 +722,33 @@ GET /t
GET /t
--- response_body
passed



=== TEST 23: verify wrong Ipv6
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local t = require("lib.test_admin")

local data = {
nodes = {
{host = "::1", port = 80, weight = 1},
},
type = "roundrobin"
}
local code, body = t.test('/apisix/admin/upstreams',
ngx.HTTP_POST,
core.json.encode(data)
)

ngx.status = code
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"invalid configuration: IPv6 address must be enclosed with '[' and ']'"}
66 changes: 66 additions & 0 deletions t/core/schema_def.t
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,69 @@ passed
}
--- response_body
passed



=== TEST 5: validate IPv6 address format in upstream nodes
--- config
location /t {
content_by_lua_block {
local schema_def = require("apisix.schema_def")
local core = require("apisix.core")
local upstream = require("apisix.upstream")
local t = require("lib.test_admin")
-- Test valid IPv6 addresses (enclosed in brackets)
local valid_cases = {
{
nodes = {
{host = "[::1]", port = 80, weight = 1},
},
type = "roundrobin"
},
{
nodes = {
{host = "[2001:db8::1]", port = 80, weight = 1},
},
type = "roundrobin"
}
}

for _, ups in ipairs(valid_cases) do
local ok, err = upstream.check_schema(ups)
if not ok then
ngx.log(ngx.ERR, "Expected valid case failed: ", err)
end
assert(ok, "Valid IPv6 case should pass: " .. (err or ""))
end

-- Test invalid IPv6 addresses (not enclosed in brackets)
local invalid_cases = {
{
nodes = {
{host = "::1", port = 80, weight = 1},
},
type = "roundrobin"
},
{
nodes = {
{host = "2001:db8::1", port = 80, weight = 1},
},
type = "roundrobin"
}
}

for i, ups in ipairs(invalid_cases) do
local ok, err = upstream.check_schema(ups)
if ok then
ngx.log(ngx.ERR, "Expected invalid case passed: ", i)
end
assert(not ok, "Invalid IPv6 case should fail")
assert(string.find(err, "IPv6 address must be enclosed with '%[' and '%]'"),
"Error should mention IPv6 enclosure requirement")
end

ngx.say("passed")
}
}
--- response_body
passed
8 changes: 4 additions & 4 deletions t/node/upstream-ipv6.t
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ hello world
{
"weight": 100,
"priority": 0,
"host": "::1",
"host": "[::1]",
"port": 1980
}
],
Expand Down Expand Up @@ -221,7 +221,7 @@ passed
GET /hello
--- error_code: 502
--- error_log
connect() to [::0.1.25.128]:80 failed
failed to set server peer [::1:1980:80] err: invalid port while connecting to upstream



Expand All @@ -237,13 +237,13 @@ connect() to [::0.1.25.128]:80 failed
{
"weight": 100,
"priority": 0,
"host": "::1",
"host": "[::1]",
"port": 1980
},
{
"weight": 100,
"priority": 0,
"host": "::1",
"host": "[::1]",
"port": 1980
}
],
Expand Down
Loading