diff --git a/Gemfile b/Gemfile index f250144a..99ab1cbe 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem 'sass', require: nil gem 'dav4rack' gem 'filesize' gem 'thread' +gem 'scrypt' platform :mri do gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic diff --git a/Gemfile.lock b/Gemfile.lock index 436ef6bd..f6d17b97 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,7 +54,10 @@ GEM i18n (~> 0.5) faraday (0.9.0) multipart-post (>= 1.2, < 3) - ffi (1.9.3) + ffi (1.9.6) + ffi-compiler (0.1.3) + ffi (>= 1.0.0) + rake filesize (0.0.3) google-api-client (0.7.1) addressable (>= 2.3.2) @@ -133,7 +136,7 @@ GEM rack (~> 1.1) unicorn (~> 4.8) raindrops (0.13.0) - rake (10.2.1) + rake (10.3.2) redis (3.0.7) redis-namespace (1.4.1) redis (~> 3.0.4) @@ -146,6 +149,9 @@ GEM sass (3.3.8) screencap (0.1.1) phantomjs + scrypt (2.0.0) + ffi-compiler (>= 0.0.2) + rake sequel (4.8.0) sequel_pg (1.6.9) pg (>= 0.8.0) @@ -242,6 +248,7 @@ DEPENDENCIES ruby-debug sass screencap + scrypt sequel (= 4.8.0) sequel_pg shotgun diff --git a/Rakefile b/Rakefile index fb4371b1..e5042035 100644 --- a/Rakefile +++ b/Rakefile @@ -188,6 +188,15 @@ task :prime_site_updated_at => [:environment] do end end +desc 'hash_ips' +task :hash_ips => [:environment] do + Site.select(:id,:ip).order(:id).all.each do |s| + next if s.ip.nil? || s.ip.match(/#{$config['ip_hash_salt']}/) + s.ip = s.ip + s.save_changes validate: false + end +end + =begin desc 'Update screenshots' task :update_screenshots => [:environment] do diff --git a/app.rb b/app.rb index 49f40b7d..338c0dcd 100644 --- a/app.rb +++ b/app.rb @@ -1216,8 +1216,7 @@ post '/admin/banip' do flash[:error] = 'IP is blank, cannot continue' redirect '/admin' end - - sites = Site.filter(ip: site.ip, is_banned: false).all + sites = Site.filter(ip: Site.hash_ip(site.ip), is_banned: false).all sites.each {|s| s.ban!} flash[:error] = "#{sites.length} sites have been banned." redirect '/admin' @@ -1495,7 +1494,7 @@ post '/site/:username/report' do |username| redirect request.referer if current_site.id == site.id report.reporting_site_id = current_site.id else - report.ip = request.ip + report.ip = Site.hash_ip request.ip end report.save @@ -1533,8 +1532,8 @@ def dashboard_if_signed_in end def require_login_ajax - halt 'You are banned.' if Site.banned_ip?(request.ip) halt 'You are not logged in!' unless signed_in? + halt 'You are banned.' if current_site.is_banned? || parent_site.is_banned? end def csrf_safe? @@ -1546,8 +1545,11 @@ def csrf_token end def require_login - require_unbanned_ip redirect '/' unless signed_in? + if current_site.is_banned || parent_site.is_banned + session[:id] = nil + redirect '/' + end end def signed_in? diff --git a/config.yml.template b/config.yml.template index 1aba4e99..afb13194 100644 --- a/config.yml.template +++ b/config.yml.template @@ -8,6 +8,7 @@ development: sidekiq_pass: ENTER PASS HERE stripe_publishable_key: fillout stripe_api_key: fillout + ip_hash_salt: "400$8$1$fc21863da5d531c1" test: database: 'postgres://neocities@127.0.0.1/neocities_test' database_pool: 1 @@ -18,3 +19,4 @@ test: sidekiq_pass: ENTER PASS HERE stripe_publishable_key: fillout stripe_api_key: fillout + ip_hash_salt: "400$8$1$fc21863da5d531c1" \ No newline at end of file diff --git a/environment.rb b/environment.rb index 4095bccc..edc67d5c 100644 --- a/environment.rb +++ b/environment.rb @@ -26,6 +26,8 @@ else end # :nocov: +raise 'hash_ip_salt is required' unless $config['ip_hash_salt'] + DB = Sequel.connect $config['database'], sslmode: 'disable', max_connections: $config['database_pool'] DB.extension :pagination diff --git a/models/site.rb b/models/site.rb index 28bcc2e4..3c9e1dd9 100644 --- a/models/site.rb +++ b/models/site.rb @@ -202,20 +202,29 @@ class Site < Sequel::Model end def ip_create_limit?(ip) - Site.where('created_at > ?', Date.today.to_time).where(ip: ip).count > IP_CREATE_LIMIT || - Site.where(ip: ip).count > TOTAL_IP_CREATE_LIMIT + hashed_ip = hash_ip ip + Site.where('created_at > ?', Date.today.to_time).where(ip: hashed_ip).count > IP_CREATE_LIMIT || + Site.where(ip: hashed_ip).count > TOTAL_IP_CREATE_LIMIT + end + + def hash_ip(ip) + SCrypt::Engine.hash_secret ip, $config['ip_hash_salt'] + end + + def banned_ip?(ip) + return true if Site.where(is_banned: true). + where(ip: hash_ip(ip)). + where(['updated_at > ?', Time.now-BANNED_TIME]). + first + + return true if BlockedIp[ip] + + false end end - def self.banned_ip?(ip) - return true if Site.where(is_banned: true). - where(ip: ip). - where(['updated_at > ?', Time.now-BANNED_TIME]). - first - - return true if BlockedIp[ip] - - false + def ip=(ip) + super self.class.hash_ip(ip) end def is_following?(site) diff --git a/tests/acceptance/signup_tests.rb b/tests/acceptance/signup_tests.rb index 9eff5628..3ab21c5d 100644 --- a/tests/acceptance/signup_tests.rb +++ b/tests/acceptance/signup_tests.rb @@ -48,6 +48,8 @@ describe 'signup' do site.site_files.length.must_equal 4 site.site_changed.must_equal false site.site_updated_at.must_equal nil + + site.ip.must_equal Site.hash_ip('127.0.0.1') end it 'fails to create for existing site' do