Cryptographically scramble IPs stored by Neocities

"There is a time when the operation of the machine becomes so odious,
makes you so sick at heart, that you can't take part; you can't even
passively take part, and you've got to put your bodies upon the gears
and upon the wheels, upon the levers, upon all the apparatus, and you've
got to make it stop. And you've got to indicate to the people who run
it, to the people who own it, that unless you're free, the machine will
be prevented from working at all."

Mario Savio
Sproul Hall Steps
University of California, Berkeley
December 3, 1964
This commit is contained in:
Kyle Drake 2014-11-07 00:41:10 -08:00
parent 1b7269c201
commit 4983a9b24e
8 changed files with 52 additions and 18 deletions

View file

@ -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

View file

@ -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

View file

@ -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

12
app.rb
View file

@ -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?

View file

@ -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"

View file

@ -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

View file

@ -202,14 +202,18 @@ 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
end
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 self.banned_ip?(ip)
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: ip).
where(ip: hash_ip(ip)).
where(['updated_at > ?', Time.now-BANNED_TIME]).
first
@ -217,6 +221,11 @@ class Site < Sequel::Model
false
end
end
def ip=(ip)
super self.class.hash_ip(ip)
end
def is_following?(site)
followings_dataset.select(:id).filter(site_id: site.id).first ? true : false

View file

@ -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