1
0
Fork 1
mirror of https://gitlab.com/mangadex-pub/mangadex_at_home.git synced 2024-01-19 02:48:37 +00:00

Cut 2.0.1

This commit is contained in:
carbotaniuman 2021-05-27 14:53:54 -05:00
parent 1ef35244d7
commit 785dc1ed7f
7 changed files with 57 additions and 8 deletions

View file

@ -17,10 +17,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Security ### Security
## [2.0.1] - 2021-03-11 ## [2.0.1] - 2021-05-27
### Added
- [2021-05-27] Added SNI check to prevent people from simply scanning nodes [@carbotaniuman].
### Changed ### Changed
- [2021-05-21] Update metrics and fix cache directory leak [@carbotaniuman]. - [2021-05-21] Update metrics and fix cache directory leak [@carbotaniuman].
- [2021-05-21] Change headers to be wildcards [@carbotaniuman]. - [2021-05-21] Change headers to be wildcards [@carbotaniuman].
- [2021-05-27] Make sending the `Server` header configurable but off by default [@carbotaniuman].
## [2.0.0] - 2021-03-11 ## [2.0.0] - 2021-03-11
### Changed ### Changed
@ -393,6 +397,7 @@ This release contains many breaking changes! Of note are the changes to the cach
- [2020-06-11] Tweaked logging configuration to reduce log file sizes by [@carbotaniuman]. - [2020-06-11] Tweaked logging configuration to reduce log file sizes by [@carbotaniuman].
[Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0...HEAD [Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0...HEAD
[2.0.1]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0...2.0.1
[2.0.0]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc14...2.0.0 [2.0.0]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc14...2.0.0
[2.0.0-rc14]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc13...2.0.0-rc14 [2.0.0-rc14]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc13...2.0.0-rc14
[2.0.0-rc13]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc12...2.0.0-rc13 [2.0.0-rc13]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0-rc12...2.0.0-rc13

View file

@ -264,6 +264,7 @@ class ServerManager(
storage, storage,
remoteSettings, remoteSettings,
settings.serverSettings, settings.serverSettings,
settings.devSettings,
settings.metricsSettings, settings.metricsSettings,
statistics, statistics,
registry, registry,

View file

@ -30,6 +30,8 @@ import io.netty.handler.codec.DecoderException
import io.netty.handler.codec.http.HttpObjectAggregator import io.netty.handler.codec.http.HttpObjectAggregator
import io.netty.handler.codec.http.HttpServerCodec import io.netty.handler.codec.http.HttpServerCodec
import io.netty.handler.codec.http.HttpServerKeepAliveHandler import io.netty.handler.codec.http.HttpServerKeepAliveHandler
import io.netty.handler.ssl.SniCompletionEvent
import io.netty.handler.ssl.SniHandler
import io.netty.handler.ssl.SslContextBuilder import io.netty.handler.ssl.SslContextBuilder
import io.netty.handler.stream.ChunkedWriteHandler import io.netty.handler.stream.ChunkedWriteHandler
import io.netty.handler.timeout.ReadTimeoutException import io.netty.handler.timeout.ReadTimeoutException
@ -41,6 +43,7 @@ import io.netty.handler.traffic.TrafficCounter
import io.netty.incubator.channel.uring.IOUring import io.netty.incubator.channel.uring.IOUring
import io.netty.incubator.channel.uring.IOUringEventLoopGroup import io.netty.incubator.channel.uring.IOUringEventLoopGroup
import io.netty.incubator.channel.uring.IOUringServerSocketChannel import io.netty.incubator.channel.uring.IOUringServerSocketChannel
import io.netty.util.DomainWildcardMappingBuilder
import io.netty.util.concurrent.DefaultEventExecutorGroup import io.netty.util.concurrent.DefaultEventExecutorGroup
import io.netty.util.internal.SystemPropertyUtil import io.netty.util.internal.SystemPropertyUtil
import mdnet.Constants import mdnet.Constants
@ -48,6 +51,7 @@ import mdnet.data.Statistics
import mdnet.logging.info import mdnet.logging.info
import mdnet.logging.trace import mdnet.logging.trace
import mdnet.logging.warn import mdnet.logging.warn
import mdnet.settings.DevSettings
import mdnet.settings.ServerSettings import mdnet.settings.ServerSettings
import mdnet.settings.TlsCert import mdnet.settings.TlsCert
import org.http4k.core.HttpHandler import org.http4k.core.HttpHandler
@ -138,6 +142,7 @@ sealed class NettyTransport(threads: Int) {
class Netty( class Netty(
private val tls: TlsCert, private val tls: TlsCert,
private val serverSettings: ServerSettings, private val serverSettings: ServerSettings,
private val devSettings: DevSettings,
private val statistics: Statistics private val statistics: Statistics
) : ServerConfig { ) : ServerConfig {
override fun toServer(http: HttpHandler): Http4kServer = object : Http4kServer { override fun toServer(http: HttpHandler): Http4kServer = object : Http4kServer {
@ -167,7 +172,29 @@ class Netty(
.channelFactory(transport.factory) .channelFactory(transport.factory)
.childHandler(object : ChannelInitializer<SocketChannel>() { .childHandler(object : ChannelInitializer<SocketChannel>() {
public override fun initChannel(ch: SocketChannel) { public override fun initChannel(ch: SocketChannel) {
ch.pipeline().addLast("ssl", sslContext.newHandler(ch.alloc())) ch.pipeline().addLast(
"ssl",
SniHandler(DomainWildcardMappingBuilder(sslContext).build())
)
ch.pipeline().addLast(
"dropHostname",
object : ChannelInboundHandlerAdapter() {
override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any) {
if (evt is SniCompletionEvent) {
if (!devSettings.disableSniCheck) {
if (!evt.hostname().endsWith("mangadex.network") &&
!evt.hostname().endsWith("localhost")
) {
ctx.close()
}
}
} else {
ctx.fireUserEventTriggered(evt)
}
}
}
)
ch.pipeline().addLast("codec", HttpServerCodec()) ch.pipeline().addLast("codec", HttpServerCodec())
ch.pipeline().addLast("keepAlive", HttpServerKeepAliveHandler()) ch.pipeline().addLast("keepAlive", HttpServerKeepAliveHandler())

View file

@ -31,6 +31,7 @@ import mdnet.logging.warn
import mdnet.metrics.GeoIpMetricsFilterBuilder import mdnet.metrics.GeoIpMetricsFilterBuilder
import mdnet.metrics.PostTransactionLabeler import mdnet.metrics.PostTransactionLabeler
import mdnet.netty.Netty import mdnet.netty.Netty
import mdnet.settings.DevSettings
import mdnet.settings.MetricsSettings import mdnet.settings.MetricsSettings
import mdnet.settings.RemoteSettings import mdnet.settings.RemoteSettings
import mdnet.settings.ServerSettings import mdnet.settings.ServerSettings
@ -46,6 +47,7 @@ fun getServer(
storage: ImageStorage, storage: ImageStorage,
remoteSettings: RemoteSettings, remoteSettings: RemoteSettings,
serverSettings: ServerSettings, serverSettings: ServerSettings,
devSettings: DevSettings,
metricsSettings: MetricsSettings, metricsSettings: MetricsSettings,
statistics: Statistics, statistics: Statistics,
registry: PrometheusMeterRegistry, registry: PrometheusMeterRegistry,
@ -109,7 +111,7 @@ fun getServer(
) )
return timeRequest() return timeRequest()
.then(addCommonHeaders()) .then(addCommonHeaders(devSettings.sendServerHeader))
.then(catchAllHideDetails()) .then(catchAllHideDetails())
.then( .then(
routes( routes(
@ -142,7 +144,7 @@ fun getServer(
GeoIpMetricsFilterBuilder(metricsSettings.enableGeoip, metricsSettings.geoipLicenseKey, registry).build() GeoIpMetricsFilterBuilder(metricsSettings.enableGeoip, metricsSettings.geoipLicenseKey, registry).build()
) )
) )
.asServer(Netty(remoteSettings.tls!!, serverSettings, statistics)) .asServer(Netty(remoteSettings.tls!!, serverSettings, devSettings, statistics))
} }
private val LOGGER = LoggerFactory.getLogger(ImageServer::class.java) private val LOGGER = LoggerFactory.getLogger(ImageServer::class.java)

View file

@ -35,12 +35,17 @@ import java.util.*
private val HTTP_TIME_FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O", Locale.ENGLISH) private val HTTP_TIME_FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O", Locale.ENGLISH)
private val LOGGER = LoggerFactory.getLogger("Application") private val LOGGER = LoggerFactory.getLogger("Application")
fun addCommonHeaders(): Filter { fun addCommonHeaders(sendServerHeader: Boolean): Filter {
return Filter { next: HttpHandler -> return Filter { next: HttpHandler ->
{ request: Request -> { request: Request ->
val response = next(request) val response = next(request)
response.header("Date", HTTP_TIME_FORMATTER.format(ZonedDateTime.now(ZoneOffset.UTC))) response.header("Date", HTTP_TIME_FORMATTER.format(ZonedDateTime.now(ZoneOffset.UTC))).let {
.header("Server", "MangaDex@Home Node ${BuildInfo.VERSION} (${Constants.CLIENT_BUILD})") if (sendServerHeader) {
it.header("Server", "MangaDex@Home Node ${BuildInfo.VERSION} (${Constants.CLIENT_BUILD})")
} else {
it
}
}
} }
} }
} }

View file

@ -47,7 +47,9 @@ data class ServerSettings(
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class DevSettings( data class DevSettings(
val devUrl: String? = null val devUrl: String? = null,
val disableSniCheck: Boolean = false,
val sendServerHeader: Boolean = false,
) )
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)

View file

@ -39,6 +39,7 @@ import org.http4k.core.Response
import org.http4k.core.Status import org.http4k.core.Status
import org.http4k.kotest.shouldHaveHeader import org.http4k.kotest.shouldHaveHeader
import org.http4k.kotest.shouldHaveStatus import org.http4k.kotest.shouldHaveStatus
import org.http4k.kotest.shouldNotHaveHeader
import org.http4k.routing.bind import org.http4k.routing.bind
import org.http4k.routing.routes import org.http4k.routing.routes
import org.ktorm.database.Database import org.ktorm.database.Database
@ -106,6 +107,12 @@ class ImageServerTest : FreeSpec() {
response.close() response.close()
} }
} }
"should not have Server header" {
val response = handler(Request(Method.GET, "/data/02181a8f5fe8cd408720a771dd129fd8/T2.png"))
response.shouldNotHaveHeader("Server")
response.close()
}
} }
"with real cache" - { "with real cache" - {