From 76d92792b78ecd9afbcc9d33be75a35e069156e4 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 21:25:51 +0800 Subject: [PATCH] For #460, fix ipv6 intranet address filter bug. 3.0.93 --- README.md | 1 + trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_mp4.hpp | 4 +- trunk/src/kernel/srs_kernel_utility.cpp | 19 ++-- trunk/src/service/srs_service_st.cpp | 2 +- trunk/src/service/srs_service_utility.cpp | 24 ++++- trunk/src/utest/srs_utest_kernel.cpp | 8 ++ trunk/src/utest/srs_utest_service.cpp | 105 +++++++++++++++++++++- 8 files changed, 144 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index d755bd761..629d93211 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 intranet address filter bug. 3.0.93 * v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92 * v3.0, 2020-01-02, For [#1042][bug #1042], improve test coverage for config. 3.0.91 * v3.0, 2019-12-30, Fix mp4 security issue, check buffer when required size is variable. diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 10dbe06ca..2ddb51420 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 92 +#define VERSION_REVISION 93 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index 6d06ea106..161f2c032 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -2169,7 +2169,7 @@ std::stringstream& srs_dumps_array(std::vector&arr, std::stringstream& ss, Sr pfn(elem, ss, dc); - if (i < limit - 1) { + if ((int)i < limit - 1) { delimiter(ss, dc); } } @@ -2192,7 +2192,7 @@ std::stringstream& srs_dumps_array(T* arr, int size, std::stringstream& ss, SrsM pfn(elem, ss, dc); - if (i < limit - 1) { + if ((int)i < limit - 1) { delimiter(ss, dc); } } diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 1cab2c969..1d091338e 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -170,25 +170,22 @@ string srs_dns_resolve(string host, int& family) { addrinfo hints; memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; + hints.ai_family = family; addrinfo* r = NULL; SrsAutoFree(addrinfo, r); - - if(getaddrinfo(host.c_str(), NULL, NULL, &r)) { + if(getaddrinfo(host.c_str(), NULL, &hints, &r)) { return ""; } - char saddr[64]; - char* h = (char*)saddr; - socklen_t nbh = sizeof(saddr); - const int r0 = getnameinfo(r->ai_addr, r->ai_addrlen, h, nbh, NULL, 0, NI_NUMERICHOST); - if(!r0) { - family = r->ai_family; - return string(saddr); + char shost[64]; + memset(shost, 0, sizeof(shost)); + if (getnameinfo(r->ai_addr, r->ai_addrlen, shost, sizeof(shost), NULL, 0, NI_NUMERICHOST)) { + return ""; } - return ""; + family = r->ai_family; + return string(shost); } void srs_parse_hostport(const string& hostport, string& host, int& port) diff --git a/trunk/src/service/srs_service_st.cpp b/trunk/src/service/srs_service_st.cpp index 00d1b4380..6cd04ba93 100644 --- a/trunk/src/service/srs_service_st.cpp +++ b/trunk/src/service/srs_service_st.cpp @@ -157,7 +157,7 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t addrinfo hints; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; addrinfo* r = NULL; diff --git a/trunk/src/service/srs_service_utility.cpp b/trunk/src/service/srs_service_utility.cpp index cc3eade17..4d19133f4 100644 --- a/trunk/src/service/srs_service_utility.cpp +++ b/trunk/src/service/srs_service_utility.cpp @@ -115,8 +115,28 @@ bool srs_net_device_is_internet(const sockaddr* addr) } } else if(addr->sa_family == AF_INET6) { const sockaddr_in6* a6 = (const sockaddr_in6*)addr; - if ((IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) || - (IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr))) { + + // IPv6 loopback is ::1 + if (IN6_IS_ADDR_LOOPBACK(&a6->sin6_addr)) { + return false; + } + + // IPv6 unspecified is :: + if (IN6_IS_ADDR_UNSPECIFIED(&a6->sin6_addr)) { + return false; + } + + // From IPv4, you might know APIPA (Automatic Private IP Addressing) or AutoNet. + // Whenever automatic IP configuration through DHCP fails. + // The prefix of a site-local address is FE80::/10. + if (IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) { + return false; + } + + // Site-local addresses are equivalent to private IP addresses in IPv4. + // The prefix of a site-local address is FEC0::/10. + // https://4sysops.com/archives/ipv6-tutorial-part-6-site-local-addresses-and-link-local-addresses/ + if (IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr)) { return false; } } diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 8f62186cc..9868749d5 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4253,6 +4253,14 @@ VOID TEST(KernelUtilityTest, CoverTimeUtilityAll) _srs_system_time_us_cache -= 300*1000 * 1000 + 1; EXPECT_TRUE(srs_update_system_time() > 0); + + if (true) { + string host; + int port = 8080; + srs_parse_hostport("3ffe:dead:beef::1", host, port); + EXPECT_EQ(8080, port); + EXPECT_STREQ("3ffe:dead:beef::1", host.c_str()); + } if (true) { string host; diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index c4dda4dd6..e75f7285d 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -36,6 +36,8 @@ using namespace std; #include #include #include +#include +#include class MockSrsConnection : public ISrsConnection { @@ -940,11 +942,30 @@ VOID TEST(TCPServerTest, CoverUtility) EXPECT_FALSE(srs_string_is_rtmp("http://")); EXPECT_FALSE(srs_string_is_rtmp("rtmp:")); + // ipv4 loopback if (true) { - sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // ipv4 intranet + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); } EXPECT_FALSE(srs_net_device_is_internet("eth0")); @@ -980,5 +1001,81 @@ VOID TEST(TCPServerTest, CoverUtility) addr.sin_addr.s_addr = htonl(0xc0a8ffff); EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); } + + // Normal ipv6 address. + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r)); + + EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r)); + + EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_UNSPECIFIED + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_SITELOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_LINKLOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_LINKLOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } }