Iptables: giden trafiği conntrack ve sahibiyle eşleştirme. Garip damlalarla çalışır


11

Iptables betiğimde olabildiğince ince taneli kurallar yazmayı deniyorum. Hangi kullanıcıların, kısmen güvenlik ve kısmen de bir öğrenme alıştırması olarak hangi hizmetleri kullanmasına izin verildiğini kısıtlıyorum.

3.6.2 çekirdeğini çalıştıran Debian 6.0.6'da iptables v1.4.16.2 kullanma.

Ancak henüz tam olarak anlamadığım bir konuya değindim ...

tüm kullanıcılar için giden portlar

Bu mükemmel çalışıyor. Genel durum izleme kuralım yok.

## Giden bağlantı noktası 81
$ IPTABLES -A ÇIKIŞ -p tcp --dport 81 -m conntrack --ctstate YENİ, KURULDU -j KABUL
$ IPTABLES -A GİRİŞ -p tcp --spor 81 -s $ MYIP -m conntrack --ctstate KURULDU -j KABUL

kullanıcı eşleşmeli giden bağlantı noktaları

## useraccount için giden bağlantı noktası 80
$ IPTABLES -A ÇIKIŞ - maç sahibi - kullanıcı sahibi useraccount -p tcp --dport 80 -m conntrack --ctstate YENİ, KURULDU --spor 1024: 65535 -j KABUL
$ IPTABLES -A GİRİŞ -p tcp --sport 80 --dport 1024: 65535 -d $ MYIP -m conntrack --ctstate KURULDU -j KABUL

Bu, 80 numaralı bağlantı noktasının yalnızca "useraccount" hesabı için kullanılmasına izin verir, ancak TCP trafiği için böyle kuralların sorunları vardır.

## Varsayılan giden günlük + engelleme kuralları
$ IPTABLES -A OUTPUT -j LOG --log-ön eki "BAD OUTGOING" - log-ip-options --log-tcp-options --log-uid
$ IPTABLES -A ÇIKIŞ -j DAMLA

Sorun

Yukarıdaki işler, kullanıcı "useraccount" mükemmel dosyaları alabilirsiniz. Sistemdeki başka hiçbir kullanıcı 80 numaralı bağlantı noktasına giden bağlantılar kuramaz.

useraccount @ host: $ wget http://cachefly.cachefly.net/10mb.test

Ama yukarıdaki wget syslog x7 bırakılan girişler bırakır:

18 Ekim 02:00:35 xxxx çekirdeği: KÖTÜ ÇIKIŞ GİRİŞİ = ÇIKIŞ = eth0 SRC = xx.xx.xx.xx DST = 205.234.175.175 LEN = 40 TOS = 0x00 PREC = 0x00 TTL = 64 ID = 12170 DF PROTO = TCP SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 PENCERE = 979 RES = 0x00 ACK URGP = 0  

UDP trafiğindeki benzer kurallar için bu düşüşleri alamıyorum. Zaten hangi kullanıcıların DNS istekleri yapabileceğini sınırlayan kurallar zaten var.

Bırakılan giden ACK paketleri, anlamadığım kök hesaptan (URGP = 0) geliyor gibi görünüyor. Useraccount'u root için değiştirdiğimde bile.

ACK paketlerinin yeni olarak kategorize edildiğine inanıyorum çünkü conntrack, 3 yollu el sıkışmasının 3. adımından sonra bağlantıları izlemeye başlıyor, ancak neden bırakılıyor?

Bu damlalar güvenle göz ardı edilebilir mi?

Düzenle

Bu yüzden, genellikle benim için iyi çalışan kurallar görüyorum:

$ IPTABLES -A ÇIKIŞ -s $ MYIP -p tcp -m tcp --dport 80 -m durum --stat YENİ, KURULU -j KABUL
$ IPTABLES -A GİRİŞ -p tcp -m tcp --spor 80 -d $ MYIP -m durum --stat KURULDU -j KABUL

"-M conntrack --ctstate" için "-m state --state" ifadesini devlet eşleşmesi geçersiz olduğu için değiştirdim.

Genel durum izleme kurallarına sahip olmak en iyi yöntem midir? Yukarıdaki kurallar doğru kabul edilmiyor mu?

Giden kullanıcıların bağlantıları üzerinde sıkı kontrol için böyle bir şey daha iyi olur mu?

$ IPTABLES -A INPUT -m conntrack --ctstate ESTABLISHED -j KABUL ET
$ IPTABLES -A OUTPUT -m conntrack --ctstate KURULDU -j KABUL

$ IPTABLES -A ÇIKIŞ -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate YENİ -m sahibi --uid-sahibi useraccount -j KABUL

$ IPTABLES -A ÇIKIŞ -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate YENİ -m sahip --uid-sahip otheraccount -j KABUL

Bu ana bilgisayar trafiği LAN'dan yönlendiriyorsa, FORWARD zinciri ve nat tablosu da dahil olmak üzere tüm kuralları yayınlayabilir misiniz?
Serge

Bu ana bilgisayar herhangi bir yönlendirme yapmıyor, trafik bu kurallarla makineden geliyor. Yalnızca belirli bir giden trafik için ilgili kuralları yayınladım.
arcX

Yanıtlar:


16

Uzun bir hikaye kısaltmak için, ACK soket kimseye ait olmadığında gönderildi. Kullanıcıya ait bir sokete ait paketlere izin vermek yerine, kullanıcıdan xgelen bir soket tarafından başlatılan bir bağlantıyla ilgili paketlere izin verin x.

Uzun hikaye.

Sorunu anlamak için, wgetHTTP isteklerinin genel olarak nasıl ve nasıl çalıştığını anlamaya yardımcı olur .

İçinde

wget http://cachefly.cachefly.net/10mb.test

wgetbir TCP bağlantısı cachefly.cachefly.netkurar ve kurulduktan sonra HTTP protokolünde şöyle bir istek gönderir: "Lütfen bana /10mb.test( GET /10mb.test HTTP/1.1) içeriğini gönderin ve bu arada, işiniz bittikten sonra lütfen bağlantıyı kesemez misiniz (Connection: Keep-alive ). bunun nedeni, sunucunun aynı IP adresindeki bir URL için yeniden yönlendirmeyle yanıt vermesi durumunda bağlantıyı yeniden kullanabilmesidir.

Şimdi sunucu ya cevap verebilir, "burada istediğiniz veri geliyor, dikkat 10MB büyük ( Content-Length: 10485760), ve evet Tamam, bağlantı açık bırakacağım". Veya verilerin boyutunu bilmiyorsa, "Veriler burada, üzgünüm bağlantıyı açık bırakamıyorum, ancak bağlantımın sonunu kapatarak veri indirmeyi ne zaman durdurabileceğinizi söyleyeceğim".

Yukarıdaki URL’de ilk durumdayız.

Bu nedenle, wgetyanıt için üstbilgileri alır almaz, 10 MB veri indirdikten sonra işinin yapıldığını bilir.

Temel olarak, wget10MB alınana ve çıkana kadar verileri okumak. Ama bu noktada yapılacak daha çok şey var. Sunucu ne olacak? Bağlantıyı açık bırakması söylendi.

Çıkmadan önce soketin dosya tanımlayıcısını wgetkapatır ( closesistem çağrısı). Bunun üzerine, closesistem sunucu tarafından gönderilen verileri kabul etmeyi bitirir ve FIN"Daha fazla veri göndermeyeceğim" şeklinde bir a gönderir . Bu noktada closegeri döner ve wgetçıkar. Artık TCP bağlantısıyla ilişkili bir soket yok (en azından herhangi bir kullanıcının sahibi olduğu). Ancak henüz bitmedi. Bunu aldıktan sonra FIN, HTTP sunucusu istemciden sonraki isteği okurken dosya sonu görür . HTTP'de bu "artık istek yok, sonumu kapatacağım" anlamına gelir. Bu yüzden FIN'sini de gönderir, "Ben de hiçbir şey göndermeyeceğim, bu bağlantı kopuyor".

Bu FIN'i aldıktan sonra müşteri bir "ACK" gönderir. Ancak, bu noktada, wgetçoktan gitti, böylece ACK herhangi bir kullanıcıdan değil. Bu yüzden güvenlik duvarınız tarafından engellenir. Sunucu ACK'yı almadığı için, FIN'yi vazgeçene kadar tekrar tekrar gönderecek ve daha fazla ACK göreceksiniz. Bu, aynı zamanda, bu ACK'ları bırakarak, sunucunun kaynaklarını (LAST-ACK durumunda bir soket tutması gerekir) gereksiz bir süre için kullandığınız anlamına gelir.

İstemci "Canlı tutma" istemediğinde veya sunucu "Canlı tutma" şeklinde yanıt vermemiş olsaydı davranış farklı olurdu.

Daha önce de belirtildiği gibi, bağlantı izleyiciyi kullanıyorsanız, yapmak istediğiniz şey KURULAN ve İLGİLİ durumlardaki her paketin yalnızca NEWpaketler hakkında endişelenmesine izin vermektir .

NEWKullanıcılardan gelen paketlere izin verir xancak kullanıcıdan gelen paketler için izin vermezseniz , kullanıcı ytarafından kurulan bağlantılar için diğer paketler xgeçer ve kullanıcı tarafından bağlantılar kurulamadığından (bağlantıyı kuracak paketleri yengellediğimizden NEW), yüzerinden geçen kullanıcı bağlantıları için herhangi bir paket olmayacaktır.


3

Bu, 80 numaralı bağlantı noktasının yalnızca "useraccount" hesabı için kullanılmasına izin verir

- en azından gösterdiğiniz kurallar aslında bunu ima etmiyor.

Ayrıca tavsiye için bir oda var - KURULAN akışlarda kullanıcı denetimi yapmayın, sadece YENİ üzerinde kontrol yapın. Ayrıca Gelen KURULDU seçeneğini kontrol ederken kaynak portunu kontrol etmede bir nokta görmüyorum, hangi portun farkı vardı, zaten conntrack'ın PoV'sinden KURULDU durumunda. Güvenlik duvarı mümkün olduğunca basit ama verimli olmalıdır, bu nedenle Occam'ın ustura yaklaşımı en uygunudur.


1
Tavsiye için teşekkürler. Genellikle basitlik içindeyim ama bu alıştırmanın amacı bu değil.
arcX

1
@arcX, bu alıştırma çok karmaşık ve tutarsız olması nedeniyle başarısız olabilir - IOW, gördüğünüz davranış netfilter içlerine (hatalar, tuhaflıklar) değil, onu kullanma şekline bağlı olabilir. Önce kural
setini
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.