implement IpTrust
This commit is contained in:
parent
a93f3724c2
commit
0e52dfa357
|
@ -135,19 +135,19 @@ object Auth extends LilaController {
|
|||
|
||||
case object Nope extends MustConfirmEmail(false)
|
||||
case object YesBecausePrint extends MustConfirmEmail(true)
|
||||
case object YesBecauseIp extends MustConfirmEmail(true)
|
||||
case object YesBecauseProxy extends MustConfirmEmail(true)
|
||||
case object YesBecauseIpExists extends MustConfirmEmail(true)
|
||||
case object YesBecauseIpSusp extends MustConfirmEmail(true)
|
||||
case object YesBecauseMobile extends MustConfirmEmail(true)
|
||||
case object YesBecauseUA extends MustConfirmEmail(true)
|
||||
|
||||
def apply(print: Option[FingerPrint])(implicit ctx: Context): Fu[MustConfirmEmail] = {
|
||||
val ip = HTTPRequest lastRemoteAddress ctx.req
|
||||
api.recentByIpExists(ip) flatMap { ipExists =>
|
||||
if (ipExists) fuccess(YesBecauseIp)
|
||||
if (ipExists) fuccess(YesBecauseIpExists)
|
||||
else print.??(api.recentByPrintExists) flatMap { printExists =>
|
||||
if (printExists) fuccess(YesBecausePrint)
|
||||
else if (HTTPRequest weirdUA ctx.req) fuccess(YesBecauseUA)
|
||||
else Env.security.ipIntel(ip).map(80 <).map { _.fold(YesBecauseProxy, Nope) }
|
||||
else Env.security.ipTrust.isSuspicious(ip).map { _.fold(YesBecauseIpSusp, Nope) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ final class Env(
|
|||
|
||||
lazy val garbageCollector = new GarbageCollector(
|
||||
userSpyApi,
|
||||
ipIntel,
|
||||
ipTrust,
|
||||
slack,
|
||||
ugcArmedSetting.get,
|
||||
system
|
||||
|
@ -167,6 +167,8 @@ final class Env(
|
|||
scheduler.once(30 seconds)(tor.refresh(_ => funit))
|
||||
scheduler.effect(TorRefreshDelay, "Refresh Tor exit nodes")(tor.refresh(firewall.unblockIps))
|
||||
|
||||
lazy val ipTrust = new IpTrust(ipIntel, geoIP, tor, firewall)
|
||||
|
||||
lazy val api = new SecurityApi(storeColl, firewall, geoIP, authenticator, emailAddressValidator, tryOAuthServer)
|
||||
|
||||
lazy val csrfRequestHandler = new CSRFRequestHandler(NetDomain)
|
||||
|
|
|
@ -9,14 +9,13 @@ import lila.user.{ User, UserRepo }
|
|||
// codename UGC
|
||||
final class GarbageCollector(
|
||||
userSpy: UserSpyApi,
|
||||
ipIntel: IpIntel,
|
||||
ipTrust: IpTrust,
|
||||
slack: lila.slack.SlackApi,
|
||||
isArmed: () => Boolean,
|
||||
system: akka.actor.ActorSystem
|
||||
) {
|
||||
|
||||
/* User just signed up and doesn't have security data yet,
|
||||
* so wait a bit */
|
||||
// User just signed up and doesn't have security data yet, so wait a bit
|
||||
def delay(user: User, ip: IpAddress, email: EmailAddress): Unit =
|
||||
if (!recentlyChecked.get(user.id) && user.createdAt.isAfter(DateTime.now minusDays 3)) {
|
||||
recentlyChecked put user.id
|
||||
|
@ -25,12 +24,12 @@ final class GarbageCollector(
|
|||
}
|
||||
}
|
||||
|
||||
private val recentlyChecked = new lila.memo.ExpireSetMemo(ttl = 5 minutes)
|
||||
private val recentlyChecked = new lila.memo.ExpireSetMemo(ttl = 3 seconds)
|
||||
|
||||
private def apply(user: User, ip: IpAddress, email: EmailAddress): Funit =
|
||||
userSpy(user) flatMap { spy =>
|
||||
badOtherAccounts(spy.otherUsers.map(_.user)) ?? { others =>
|
||||
lila.common.Future.exists(spy.ips)(isBadIp).map {
|
||||
lila.common.Future.exists(spy.ips)(ipTrust.isSuspicious).map {
|
||||
_ ?? {
|
||||
val ipBan = spy.usersSharingIp.forall { u =>
|
||||
isBadAccount(u) || !u.seenAt.exists(DateTime.now.minusMonths(2).isBefore)
|
||||
|
@ -49,13 +48,6 @@ final class GarbageCollector(
|
|||
(others.size > 1 && others.forall(isBadAccount) && others.headOption.exists(_.disabled)) option others
|
||||
}
|
||||
|
||||
private def isBadIp(ip: UserSpy.IPData): Fu[Boolean] = if (ip.blocked ||
|
||||
ip.location == Location.unknown ||
|
||||
ip.location == Location.tor ||
|
||||
ip.location.shortCountry == "Iran" // some undetected proxies
|
||||
) fuccess(true)
|
||||
else ipIntel(ip.ip).map { 75 < _ }
|
||||
|
||||
private def isBadAccount(user: User) = user.troll || user.engine
|
||||
|
||||
private def collect(user: User, email: EmailAddress, others: List[User], ipBan: Boolean): Funit = {
|
||||
|
|
|
@ -15,15 +15,9 @@ final class IpIntel(asyncCache: lila.memo.AsyncCache.Builder, lichessEmail: Stri
|
|||
}
|
||||
|
||||
def failable(ip: IpAddress): Fu[Int] =
|
||||
if (blackList.exists(ip.value.startsWith)) fuccess(90)
|
||||
if (IpIntel isBlacklisted ip) fuccess(90)
|
||||
else cache get ip
|
||||
|
||||
// Proxies ipintel doesn't detect
|
||||
private val blackList = List(
|
||||
"5.121.",
|
||||
"5.122."
|
||||
)
|
||||
|
||||
private val cache = asyncCache.multi[IpAddress, Int](
|
||||
name = "ipIntel",
|
||||
f = ip => {
|
||||
|
@ -44,3 +38,14 @@ final class IpIntel(asyncCache: lila.memo.AsyncCache.Builder, lichessEmail: Stri
|
|||
expireAfter = _.ExpireAfterAccess(3 days)
|
||||
)
|
||||
}
|
||||
|
||||
object IpIntel {
|
||||
|
||||
// Proxies ipintel doesn't detect
|
||||
private val blackList = List(
|
||||
"5.121.",
|
||||
"5.122."
|
||||
)
|
||||
|
||||
def isBlacklisted(ip: IpAddress): Boolean = blackList.exists(ip.value.startsWith)
|
||||
}
|
||||
|
|
22
modules/security/src/main/IpTrust.scala
Normal file
22
modules/security/src/main/IpTrust.scala
Normal file
|
@ -0,0 +1,22 @@
|
|||
package lila.security
|
||||
|
||||
import lila.common.IpAddress
|
||||
|
||||
case class IpTrust(intelApi: IpIntel, geoApi: GeoIP, torApi: Tor, firewallApi: Firewall) {
|
||||
|
||||
def isSuspicious(ip: IpAddress): Fu[Boolean] =
|
||||
if (IpIntel isBlacklisted ip) yep
|
||||
else if (firewallApi blocksIp ip) yep
|
||||
else if (torApi isExitNode ip) yep
|
||||
else {
|
||||
val location = geoApi orUnknown ip
|
||||
if (location == Location.unknown || location == Location.tor) yep
|
||||
else if (location.shortCountry == "Iran") yep // some undetected proxies
|
||||
else if (location.shortCountry == "United Arab Emirates") yep // some undetected proxies
|
||||
else intelApi(ip).map { 75 < _ }
|
||||
}
|
||||
|
||||
def isSuspicious(ipData: UserSpy.IPData): Fu[Boolean] = isSuspicious(ipData.ip)
|
||||
|
||||
private val yep = fuccess(true)
|
||||
}
|
Loading…
Reference in a new issue